«کاربر بتواند سفارش را لغو کند» یک نیاز قابل فهم است، اما هنوز برای پیادهسازی و آزمون کافی نیست. کدام سفارش؟ تا چه زمانی؟ اگر پرداخت شده باشد چه اتفاقی میافتد؟ اگر کاربر دو بار درخواست بدهد، نتیجه چیست؟ تفاوت پاسخها میتواند رفتار مالی و عملیاتی کاملاً متفاوتی بسازد.
در بخش قبل، سفارش، تلاش پرداخت و درخواست بازپرداخت را از هم جدا کردیم. حالا همان واژهها را به مثالهای قابل بررسی تبدیل میکنیم. پیشنیاز، شناخت مسیر سفارش نمونه است. خروجی این بخش مجموعهای کوچک از سناریوهای پذیرش و موارد مرزی است که طراح، توسعهدهنده و مسئول کسبوکار بتوانند دربارهشان توافق کنند.
از جمله کلی به یک وضعیت مشخص برسیم
برای شروع، یک سفارش پرداختشده و هنوز ارسالنشده را در نظر میگیریم. کاربر مجاز درخواست لغو میدهد. انتظار اولیه این است که سفارش لغو شود و درخواست بازپرداخت ثبت شود؛ نه اینکه فوراً پول بازگشته اعلام شود. این تفاوت از زبان دقیق بخش قبل میآید.
حالا میتوان درباره همین نمونه سؤال پرسید: آیا ثبت لغو و درخواست بازپرداخت باید با هم سازگار باشند؟ پاسخ درگاه چه زمانی میرسد؟ صفحه کاربر تا آن زمان چه میگوید؟ یک مثال مشخص، ابهام را زودتر از یک فهرست بلند صفت مثل «امن و سریع» آشکار میکند.
وضعیت اولیه، اقدام و نتیجه را جدا بنویسیم
هر سناریو باید زمینه لازم، عمل مورد بررسی و نتیجه قابل مشاهده داشته باشد. اگر این سه با هم مخلوط شوند، معلوم نیست شکست آزمون به کدام فرض مربوط است. زمینه را به اطلاعات مؤثر محدود کنید؛ رنگ دکمه برای آزمون قاعده لغو معمولاً ضروری نیست.
Scenario: Cancel a paid order before dispatch
Given an order is paid and not dispatched
And the customer is allowed to manage that order
When the customer requests cancellation
Then the order is cancelled
And one refund request is recorded
And the refund is not reported as completed
این متن یک مشخصات رفتاری آموزشی است. در این اجرا به پیادهسازی stepها وصل نشده و آزمون خودکار اجراشده محسوب نمیشود. ارزش فعلی آن در روشنکردن انتظارهاست؛ بعداً میتوان همان رفتار را در لایه مناسب به آزمون متصل کرد.
نتیجه را قابل مشاهده تعریف کنیم
عبارت «سیستم درست عمل میکند» چیزی برای بررسی ندارد. باید بدانیم چه وضعیتی ثبت میشود، چه پاسخی به کاربر میرسد و چه اثری نباید رخ دهد. اگر فقط پیام موفقیت را بسنجیم، ممکن است داده ناسازگار پشت آن پنهان بماند.
در نمونه لغو، میتوان ثبت یک درخواست بازپرداخت و نبود درخواست تکراری را بررسی کرد. در آزمون رابط، پیام مناسب و وضعیت تازه سفارش دیده میشود. در آزمون یکپارچه، ارتباط واقعی ذخیره سفارش و درخواست بررسی میشود. هر لایه بخشی از رفتار را میسنجد؛ لازم نیست همه بررسیها در یک آزمون بزرگ جمع شوند.
جدول مثال، اختلاف سیاست را آشکار میکند
بهجای بحث انتزاعی درباره همه سفارشها، چند وضعیت را کنار هم بگذاریم. جدول زیر سیاست پیشنهادی محصول نمونه است و باید در محصول واقعی با مسئول مربوط توافق شود. اگر یک ردیف هنوز جواب ندارد، آن را مجهول ثبت کنید؛ حدس توسعهدهنده نباید بیصدا به قاعده کسبوکار تبدیل شود.
| وضعیت اولیه | اقدام | انتظار در مثال |
|---|---|---|
| پرداختشده، ارسالنشده | لغو توسط مالک | لغو و ثبت درخواست بازپرداخت |
| ارسالشده | لغو از همین مسیر | رد کنترلشده و معرفی مسیر مناسب |
| لغوشده با درخواست موجود | تکرار لغو | بدون درخواست مالی تازه |
| متعلق به کاربر دیگر | درخواست لغو | رد بدون افشای اطلاعات سفارش |
| پرداخت نامشخص | لغو | نیاز به تعیین سیاست؛ نتیجه را حدس نمیزنیم |
ردیف آخر شاید مهمترین خروجی جلسه باشد. جدول فقط برای تأیید موارد معلوم نیست؛ باید پرسشهایی را پیدا کند که مانع پیادهسازی درستاند. بعد از تصمیم، دلیل و مثال مربوط را هم ثبت کنیم.
مرز زمانی را دقیق کنیم
اگر قاعده بگوید «تا قبل از ارسال»، باید معلوم باشد مرجع ارسال چیست: تغییر وضعیت داخلی، تحویل به پیک یا دریافت تأیید از سرویس بیرونی؟ اگر محدودیت زمانی داریم، لحظه دقیق مرز و منطقه زمانی باید روشن باشند.
سه نمونه قبل از مرز، روی مرز و بعد از مرز معمولاً مفیدند. ساعت واقعی سیستم را در آزمون بیدلیل دخیل نکنید؛ زمان باید قابل کنترل باشد تا نتیجه تکرارپذیر بماند. جزئیات جداسازی زمان را در بخش تزریق وابستگی بررسی میکنیم.
تکرار درخواست یک حالت عادی است
کاربر ممکن است دوبار دکمه بزند یا پس از قطع ارتباط دوباره تلاش کند. نباید این رفتار را فقط خطای کاربر بدانیم. مشخص کنید تلاش دوم همان نتیجه قبلی را برمیگرداند یا با پیام قابل فهم رد میشود؛ در هر صورت اثر مالی ناخواسته نباید ایجاد شود.
این انتظار باید در سرور هم برقرار باشد، نه فقط با غیرفعالکردن دکمه. آزمون رابط میتواند جلوگیری از کلیک تکراری را بسنجد، اما آزمون قرارداد و ذخیرهسازی باید رفتار دو درخواست را هم بررسی کند. این دو مسئولیت مکملاند.
همزمانی را در سناریو جا بدهیم
فرض کنید مسئول ارسال در همان زمان، سفارش را وارد مرحله بعد میکند. صفحه کاربر هنوز وضعیت قبلی را نشان میدهد. حالا تصمیم باید بر اساس وضعیت معتبر سرور گرفته شود و رابط نتیجه اختلاف را بفهمد. یک تست ساده روی شیء قدیمی این مسئله را پوشش نمیدهد.
سناریوی همزمانی باید با ابزار و دیتابیس متناسب بررسی شود. در این بخش، نتیجه آزمایش رقابت گزارش نمیکنیم؛ فقط انتظار را ثبت میکنیم تا در طراحی تراکنش و آزمون یکپارچه گم نشود. عبارت «معمولاً همزمان نمیشود» جای قاعده نیست.
خطای زیرساخت را با رد دامنه یکی نکنیم
رد لغو بهدلیل ارسالشدن سفارش با قطع ارتباط دیتابیس تفاوت دارد. در اولی، سیستم تصمیم معتبر گرفته است؛ در دومی ممکن است نتیجه عملیات نامعلوم باشد. پیام، امکان تلاش مجدد و ثبت رویداد باید با این تفاوت هماهنگ باشند.
همچنین شکست ارسال پیام اطلاعرسانی نباید خودبهخود به معنای شکست ثبت لغو باشد. لازم است مشخص کنیم چه چیزی پایدار شده و کدام کار جانبی هنوز انجام نشده است. همین تمایز بعداً در طراحی خطا و کار پسزمینه کاربرد دارد.
سناریو را از جزئیات رابط مستقل نگه داریم
برای قاعده لغو، نوشتن اینکه کاربر روی دکمه قرمز بالای جدول کلیک میکند، ممکن است آزمون را به چیدمان گره بزند. رفتار اصلی «درخواست لغو» است. در آزمون رابط، مسیر دسترسی به آن عمل را بررسی میکنیم؛ در آزمون دامنه، نیازی به رنگ و محل دکمه نیست.
این تفکیک اجازه میدهد ظاهر تغییر کند ولی قرارداد اصلی حفظ شود. البته نیازهای دسترسپذیری یا دیدهشدن پیام هم رفتار واقعیاند و باید آزمون خودشان را داشته باشند. مستقلبودن سناریوی دامنه به معنی بیاهمیتبودن رابط نیست.
مثالها را با تغییر نیاز زنده نگه داریم
وقتی بازپرداخت جزئی اضافه شد، جدول قدیمی باید دوباره مرور شود. شاید «یک درخواست بازپرداخت» هنوز درست باشد، اما مبلغ و اقلام نیاز به تعریف تازه داشته باشند. اگر مثالها از تصمیمها جدا بمانند، خیلی زود سندی میشوند که رفتار قدیمی را توضیح میدهد.
در بازبینی تغییر، از نویسنده بخواهید بگوید کدام سناریو عوض شده و کدام ثابت مانده است. این سؤال به بازبین کمک میکند اثر واقعی تغییر را ببیند. تغییر دهها تست بدون توضیح رفتار، همین فرصت را از بین میبرد.
تمرین برای جلسه بعد
نیاز «کاربر بتواند بخشی از سفارش را پس بدهد» را بردارید. سه وضعیت اولیه، دو مورد مرزی و یک حالت تکرار بنویسید. سپس مشخص کنید چه پرسشی درباره مبلغ یا وضعیت هنوز بیپاسخ است. همین مجهولها را پیش از پیادهسازی با صاحب قاعده روشن کنید.
در بخش بعد، پیچیدگی ناشی از این قواعد را از پیچیدگی اتفاقی پیادهسازی جدا میکنیم. هدف، حذف مسئله واقعی نیست؛ میخواهیم راهحلی انتخاب کنیم که قواعد روشن را پشت لایهها و شرطهای اضافی پنهان نکند.
مرجع قالب سناریو
مرجع رسمی Gherkin در Cucumber ساختار سناریو و کلیدواژهها را توضیح میدهد. مثالها و سیاستهای سفارش این مقاله تألیفیاند و باید با دامنه محصول واقعی تطبیق داده شوند.
