یک تست خودکار سبز می‌تواند از نبودن تست خطرناک‌تر باشد؛ اگر هیچ‌وقت در برابر خرابی واقعی قرمز نشود، فقط «اعتماد کاذب» را با سرعت بیشتری وارد پایپ‌لاین می‌کند. همین مسئله درباره تست‌کیسی که نتیجهٔ مورد انتظار آن فقط «عملیات موفق است» صدق می‌کند. بازبینی همتا یا Peer Review قرار نیست یک امضای تشریفاتی زیر این مصنوعات بگذارد؛ باید نشان دهد تست کدام ریسک را می‌سنجد، با چه اوراکلی درباره نتیجه قضاوت می‌کند و چه شاهدی برای تصمیم تیم باقی می‌گذارد.

در این راهنما، بازبینی تست‌کیس و کد تست را به‌صورت یک فرایند ریسک‌محور و مبتنی بر شواهد طراحی می‌کنیم. چک‌لیست‌ها، نمونهٔ پرداخت ایرانی، مثال کد Playwright، روش نوشتن کامنت، نقش ابزارها و معیارهای سلامت فرایند را خواهید دید. هدف «کامل اعلام‌کردن کیفیت» نیست؛ هدف، کم‌کردن عدم‌قطعیت شناخته‌شده پیش از ادغام یا انتشار است.

بازبینی تست‌کیس و کد تست چیست؟

بازبینی همتای تست، ارزیابی نظام‌مند یک مصنوع تست توسط فرد یا افراد دیگری غیر از نویسنده است. مصنوع می‌تواند تحلیل ریسک، طراحی تست، تست‌کیس، داده، کد اتوماسیون، اوراکل، تنظیمات محیط یا گزارش اجرا باشد. بازبین می‌پرسد: «اگر رفتار محصول غلط شود، این تست به دلیل درست و با پیام قابل‌اقدام شکست می‌خورد؟»

سه مرز مهم را از ابتدا روشن کنید:

  • Review با اجرای تست یکی نیست: خواندن و استدلال‌کردن، خطاهای طراحی و فرض‌های پنهان را پیدا می‌کند؛ اجرا رفتار واقعی را مشاهده می‌کند. هر دو لازم‌اند.
  • Review با تحلیل استاتیک یکی نیست: Linter، کامپایلر و اسکنر الگوهای ماشینی را می‌بینند؛ انسان درباره ریسک کسب‌وکار، معنای نتیجه و خلأ سناریو داوری می‌کند.
  • Approval تضمین کیفیت نیست: تأیید یعنی شواهد برای سطح ریسک توافق‌شده کافی است، نه اینکه هیچ نقصی باقی نمانده است.

در واژگان آزمون نرم‌افزار، Review نوعی تست ایستا است. فصل تست ایستای سیلابس CTFL نسخهٔ ۴.۰.۱ مؤسسه ISTQB نقش‌ها، فعالیت‌ها و عوامل موفقیت بازبینی را توضیح می‌دهد. اما تیم شما باید آن اصول را با ریسک محصول و جریان تحویل خودش عملیاتی کند.

چرا یک چک‌لیست عمومی کافی نیست؟

چک‌کردن عنوان، پیش‌شرط، مراحل و نتیجهٔ مورد انتظار مفید است، ولی نمی‌گوید آیا تست اصلاً مسئلهٔ مهمی را هدف گرفته است. یک تست‌کیس می‌تواند از نظر نگارشی بی‌نقص باشد و در عین حال واحد پول را اشتباه بفهمد، اثر جانبی مالی را نسنجد یا callback تکراری درگاه را نادیده بگیرد. کد تست نیز ممکن است تمیز و ماژولار باشد، اما فقط متن «موفق» را ببیند و ثبت دوباره تراکنش در دفتر کل را از دست بدهد.

از سوی دیگر، قانون‌های ثابت مانند «هر تغییر دو بازبین می‌خواهد»، «جلسه باید ۶۰ دقیقه باشد» یا «بیش از ۴۰۰ خط قابل‌بازبینی نیست» بدون زمینه قابل‌دفاع نیستند. اصلاح یک غلط املایی و تغییر منطق idempotency پرداخت، شواهد و تخصص یکسان نمی‌خواهند. فرایند خوب، عمق بازبینی را با پیامد خطا تنظیم می‌کند.

مدل شواهد بازبینی: از ریسک تا تصمیم

برای هر تست این زنجیره را دنبال کنید:

  1. ریسک و نیت: کدام شکست برای کاربر، کسب‌وکار یا عملیات مهم است؟
  2. مبنای تست: انتظار از کجا آمده؛ نیازمندی، قرارداد API، قانون دامنه، رخداد تولید یا تصمیم محصول؟
  3. محرک، وضعیت و داده: چه ورودی و پیش‌شرطی رفتار را فعال می‌کند و چرا نمایندهٔ ریسک است؟
  4. Oracle: چه مشاهده‌ای درست و غلط را از هم جدا می‌کند؟
  5. شاهد: چه خروجی قابل‌ردیابی مانند لاگ، پاسخ API، رکورد دفتر کل یا Trace باقی می‌ماند؟
  6. استقلال و تکرارپذیری: آیا ترتیب اجرا، زمان، دادهٔ مشترک یا سرویس بیرونی نتیجه را عوض می‌کند؟
  7. ایمنی: آیا داده شخصی، کلید، پول واقعی یا پاک‌سازی مخرب درگیر است؟
  8. مالک و تصمیم: چه کسی اصلاح را انجام می‌دهد و چه کسی ریسک باقی‌مانده را می‌پذیرد؟

این مدل عمداً با تست مبتنی بر ریسک و ماتریس احتمال/اثر همسو است، اما جای آن مقاله را نمی‌گیرد. اینجا ریسک به «عمق بازبینی و حداقل شواهد» تبدیل می‌شود.

چه چیزهایی باید بازبینی شوند؟

محدودکردن دامنه به فایل تست یا فرم تست‌کیس، خطای رایجی است. نتیجهٔ تست محصول یک سامانهٔ کوچک از چند مصنوع وابسته است:

  • Test Basis: نیازمندی، معیار پذیرش، قرارداد، Threat Model یا شرح Incident؛
  • تحلیل ریسک، پوشش و دلیل انتخاب سطح تست؛
  • سناریو، پیش‌شرط، داده و نتیجهٔ مورد انتظار؛
  • کد تست، Fixture، Helper، Driver، Page Object و Test Double؛
  • نسخهٔ مرورگر، سرویس، Schema، Feature Flag، زمان و پیکربندی محیط؛
  • Oracle و نقطهٔ مشاهده، از UI تا API و پایگاه داده؛
  • گزارش اجرا، Log، Screenshot، Trace و شناسهٔ Build؛
  • روش ساخت، نگهداری و حذف دادهٔ تست.

برای داده‌های بانکی، شماره موبایل یا شناسه ملی، سیاست تولید و ماسک‌کردن داده نیز جزو Review است. راهنمای مدیریت داده تست و داده مصنوعی این مرز را با جزئیات پوشش می‌دهد.

سطح بازبینی را با ریسک تعیین کنید

پیش از درخواست Review، تغییر را در یکی از سطح‌های زیر قرار دهید. این جدول نقطهٔ شروع است و باید با معماری و تعهدات سازمان شما تنظیم شود.

سطح نمونه حداقل مسیر بازبینی شاهد مورد انتظار
کم اصلاح متن، نام‌گذاری یا Refactor بدون تغییر رفتار کنترل ماشینی + خودبازبینی؛ در صورت سیاست تیم، ادغام ساده Diff کوچک، Lint/Build سبز، توضیح عدم تغییر رفتار
متوسط سناریوی جدید، تغییر Oracle یا Fixture مشترک یک بازبین مسلط به دامنه یا لایهٔ تست پیوند به Basis، اجرای قبل/بعد، پوشش مرزی و شواهد استقلال
زیاد پرداخت، مجوز، حریم خصوصی، Migration یا پاک‌سازی داده بازبین دامنه + متخصص مرتبط؛ مالک ریسک نام‌برده Negative proof، مسیر خطا، امنیت داده، Rollback و ریسک باقی‌مانده

تعداد افراد هدف نیست. یک بازبین واجد صلاحیت بهتر از سه تأیید سطحی است. اگر تغییر چند حوزه مانند دیتابیس، امنیت و UI را لمس می‌کند، برای هر حوزه تصمیم‌گیر مناسب داشته باشید. راهنمای رسمی Code Review در GitLab نیز بازبینی تخصصی را بر اساس نوع تغییر تفکیک می‌کند.

نقش‌ها و حق تصمیم را صریح کنید

  • نویسنده: بستهٔ بازبینی کامل می‌سازد، خودبازبینی می‌کند و برای هر کامنت پاسخ یا اصلاح قابل‌ردیابی می‌دهد.
  • بازبین: ریسک، معنای تست و شواهد را به چالش می‌کشد؛ مسئول طراحی کامل راه‌حل به جای نویسنده نیست.
  • متخصص دامنه: قانون کسب‌وکار، امنیت، پایگاه داده، دسترس‌پذیری یا زیرساخت را در محدودهٔ اعلام‌شده بررسی می‌کند.
  • مالک تصمیم: تعارض را حل می‌کند و اگر Gap پذیرفته شد، مالک و تاریخ بازنگری آن را ثبت می‌کند.

تأیید یک نفر نباید به معنای تأیید بخش‌هایی باشد که ندیده است. بازبین می‌تواند بنویسد: «Oracle و سناریوهای پرداخت را بررسی کردم؛ پیکربندی CI در محدودهٔ من نبود.» این جمله از یک LGTM مبهم ارزشمندتر است.

چه چیزی را ماشین بررسی کند و چه چیزی را انسان؟

هر قاعدهٔ قطعی و تکرارشونده را تا جای ممکن خودکار کنید: Format، Lint، Type Check، Compile، Schema Validation، Secret Scan، Dependency Scan، تست‌های واحد Helperها و اجرای انتخابی Suite. مقالهٔ تحلیل استاتیک کد و طراحی Quality Gate نشان می‌دهد چگونه هشدار ماشینی را بدون ایجاد نویز وارد تصمیم کنید.

زمان انسان را برای پرسش‌های معنایی نگه دارید:

  • آیا ریسک و کاربر آسیب‌دیده درست شناخته شده‌اند؟
  • آیا Oracle نتیجهٔ کسب‌وکاری را می‌سنجد یا فقط جزئیات پیاده‌سازی را؟
  • کدام فرض درباره زمان، واحد پول، Locale یا وابستگی بیرونی پنهان مانده است؟
  • آیا Test Double به اندازهٔ لازم با سرویس واقعی همخوان است؟
  • آیا شکست تست قابل‌فهم، قابل‌بازتولید و قابل‌اقدام است؟
  • آیا هزینهٔ نگهداری با ریسکی که تست کاهش می‌دهد متناسب است؟

اسکنر امنیتی جای مرور انسانی مسیرهای حساس را نمی‌گیرد. OWASP Code Review Guide بر نقش بازبینی دستی در کنار ابزارهای خودکار امنیت تأکید می‌کند و چارچوب SSDF نسخهٔ ۱.۱ مؤسسه NIST نیز فعالیت‌های امنیت نرم‌افزار را بخشی از چرخهٔ توسعه می‌داند.

بستهٔ آمادهٔ بازبینی بسازید

بازبین نباید با جست‌وجو در Ticketها حدس بزند تغییر برای چیست. توضیح Merge Request یا رکورد Test Management حداقل این موارد را داشته باشد:

  1. هدف، ریسک و کاربر یا سرویس متأثر؛
  2. تغییر انجام‌شده و چیزهایی که عمداً خارج از دامنه‌اند؛
  3. پیوند به نیازمندی، Incident، قرارداد یا تصمیم معماری؛
  4. Diff مصنوعات تست و نسخهٔ محیط/وابستگی؛
  5. شاهد اینکه تست در وضعیت معیوب شکست می‌خورد و پس از اصلاح سبز می‌شود؛
  6. شناسهٔ اجرا، Commit SHA، داده، Log یا Trace لازم برای بازتولید؛
  7. Gapها، محدودیت‌ها و ریسک باقی‌مانده؛
  8. برنامهٔ انتشار، Rollback یا پاک‌سازی برای تغییر پرریسک.

اثبات قرمزشدن می‌تواند اجرای تست روی نسخهٔ قبل از Fix، بازگرداندن موقت شرط معیوب، Mutation هدفمند یا بازتولید Incident باشد. صرف Screenshot سبز نشان نمی‌دهد تست توان کشف خطا دارد.

فرایند بازبینی از درخواست تا تصمیم

۱. آماده‌سازی و خودبازبینی نویسنده

نویسنده Diff را مانند یک بازبین از ابتدا می‌خواند، نویز قالب‌بندی را جدا می‌کند، تست‌ها را در محیط مشخص اجرا می‌کند و بستهٔ شواهد را کامل می‌سازد. تغییرهای منسجم و کوچک‌تر معمولاً فهم آسان‌تری دارند، اما اندازهٔ عددی نباید جای پیچیدگی معنایی را بگیرد.

۲. بررسی ناهمگام و ثبت یافته‌ها

بازبین ابتدا هدف و Basis، سپس طراحی و در پایان جزئیات کد را می‌خواند. بررسی فقط خط‌های تغییرکرده کافی نیست؛ گاهی Context فایل، Fixture مشترک یا رفتار سرویس لازم است. در راهنمای «در Code Review دنبال چه باشیم» گوگل، طراحی، کارکرد، پیچیدگی، تست، Context و نیاز به متخصص حوزه صریحاً مطرح شده‌اند.

۳. اصلاح، پاسخ و اجرای مجدد

نویسنده کامنت را Resolve نمی‌کند مگر اینکه اصلاح، پاسخ مستدل یا توافق ثبت‌شده وجود داشته باشد. تغییر Oracle یا داده می‌تواند معنای تست را عوض کند؛ بنابراین پس از اصلاح باید اجرای مرتبط تکرار و شاهد تازه پیوست شود.

۴. تصمیم و ثبت ریسک باقی‌مانده

خروجی Review یکی از این سه حالت است: تأیید با شواهد کافی، درخواست اصلاح الزامی، یا پذیرش مستند Gap توسط مالک مجاز. «بعداً درست می‌کنیم» بدون Owner و تاریخ انقضا تصمیم نیست.

بازبینی ناهمگام یا جلسه؟

حالت پیش‌فرض را ناهمگام نگه دارید تا استدلال و تصمیم برای آینده باقی بماند. جلسه زمانی ارزش دارد که مدل دامنه پیچیده است، مشاهدهٔ رفتار UI لازم است، تعارض پس از تبادل شواهد حل نشده یا رخداد حساسی نیاز به Threat Modeling مشترک دارد. پس از جلسه، نتیجه و اقدام‌ها را در همان MR یا ابزار مدیریت تست ثبت کنید.

برای مدت جلسه نسخهٔ جادویی وجود ندارد. اگر بازبین پس از زمان معقول هنوز هدف یا Diff را نمی‌فهمد، بسته را روشن‌تر یا تغییر را منسجم‌تر کنید. استاندارد Code Review گوگل نیز به‌جای کمال‌گرایی، بهبود سلامت کد و تقدم داده و واقعیت فنی بر سلیقه را معیار می‌گذارد.

چک‌لیست بازبینی طراحی و تست‌کیس

نیت، Basis و پوشش ریسک

  • نام تست، رفتار و نتیجه را بیان می‌کند، نه فقط شمارهٔ Ticket؟
  • منبع انتظار و نسخهٔ آن مشخص است؟ اگر منابع تعارض دارند، تصمیم ثبت شده است؟
  • سناریو به ریسک اولویت‌دار وصل است و دلیل سطح تست روشن است؟
  • Happy Path، مرزها، خطاها، مجوز، تکرار، هم‌زمانی یا بازیابی متناسب با ریسک پوشش دارند؟
  • موارد خارج از دامنه و دلیل آن‌ها آشکارند؟

پیش‌شرط، داده و محرک

  • وضعیت اولیه قابل‌ساخت و قابل‌پاک‌سازی است؟
  • داده فقط «نمونه» نیست و کلاس هم‌ارزی یا مقدار مرزی موردنظر را نمایندگی می‌کند؟
  • واحد، Locale، Encoding، منطقهٔ زمانی و قالب تقویم صریح‌اند؟
  • شناسه‌ها یکتا هستند و وابستگی پنهان به ترتیب اجرای تست وجود ندارد؟
  • دادهٔ واقعی حساس حذف، ناشناس یا با دادهٔ مصنوعی جایگزین شده است؟

Oracle و نتیجهٔ مورد انتظار

  • نتیجه دقیق، مشاهده‌پذیر و قابل‌قضاوت است؟
  • اثر جانبی مهم مانند Ledger، موجودی، رویداد یا Audit Log نیز دیده می‌شود؟
  • Oracle رفتار کاربر/قرارداد را می‌سنجد، نه همان الگوریتمی را که محصول اجرا می‌کند؟
  • خطا، کد وضعیت و پیام به اندازهٔ کافی خاص‌اند و به ترجمه یا متن شکننده وابسته نیستند؟
  • مشخص است چه شاهدی نتیجه را اثبات می‌کند و چقدر نگه داشته می‌شود؟

قابلیت اجرا و نگهداری

  • مراحل کمینه، بدون ابهام و مستقل از دانش شفاهی‌اند؟
  • سناریو با تست دیگر هم‌پوشانی بی‌دلیل ندارد و هدف یکتای آن معلوم است؟
  • تغییر کوچک UI یا دادهٔ نامرتبط باعث بازنویسی گسترده نمی‌شود؟
  • مالک، اولویت، وضعیت Automation و تاریخ بازنگری مشخص‌اند؟

مثال: بازبینی تست‌کیس پرداخت ایرانی

نسخهٔ ضعیف

عنوان بررسی پرداخت موفق
داده مبلغ ۱۰۰٬۰۰۰
مراحل سفارش بسازید، به درگاه بروید و پرداخت کنید.
انتظار پرداخت موفق باشد و پیام موفقیت نمایش داده شود.

این تست واحد پول را نمی‌گوید، موفقیت را فقط از UI می‌فهمد و درباره تراکنش تکراری، callback، وضعیت سفارش و Ledger ساکت است. حتی اگر همیشه سبز باشد، ریسک «کسر وجه بدون ثبت سفارش» را نمی‌سنجد.

نسخهٔ قابل‌بازبینی

ریسک callback تکراری PSP باعث دو ثبت مالی یا دو بار تغییر وضعیت سفارش شود.
Basis قرارداد Payment v3، قانون دامنهٔ idempotency و Incident شمارهٔ PAY-۱۸۴.
پیش‌شرط سفارش یکتای A با مبلغ ۱٬۰۰۰٬۰۰۰ ریال؛ PSP sandbox؛ زمان ثابت ۱۴:۳۰ تهران و ذخیره UTC.
محرک callback معتبر با authority یکسان دو بار ارسال شود؛ بار دوم با فاصلهٔ ۳ ثانیه.
Oracle هر دو پاسخ طبق قرارداد idempotent؛ یک Payment و دقیقاً یک Ledger entry؛ وضعیت سفارش Paid؛ هیچ رویداد تکراری برای fulfillment.
شاهد Correlation ID، پاسخ‌های API، Query فقط‌خواندنی Ledger و Trace سرویس‌ها با دادهٔ حساس ماسک‌شده.
مرزها ارقام فارسی و لاتین در ورودی نمایش، تبدیل تومان فقط در UI، ذخیره و قرارداد همواره ریال؛ UTC/Tehran صریح.
پاک‌سازی داده با run_id یکتا و TTL؛ عدم استفاده از کارت یا شماره موبایل واقعی.

بازبین اکنون می‌تواند درباره مدل ریسک، قدرت Oracle و نقطهٔ مشاهده بحث کند. برای مسیرهایی که مثال‌های ازپیش‌نوشته‌شده کافی نیستند، یک Session کوتاه تست اکتشافی ساختاریافته می‌تواند ابهام‌های تازه را کشف کند؛ خروجی آن باید دوباره به Basis یا پوشش پایدار برگردد.

چک‌لیست بازبینی کد تست

رفتار و قدرت Oracle

  • تست از API یا مسیر واقعی محصول استفاده می‌کند و منطق تولید را در خودش کپی نکرده است؟
  • Assertion نتیجهٔ مهم را می‌سنجد، نه فقط نبود Exception یا وجود یک عنصر؟
  • تست با ایجاد خرابی هدفمند واقعاً قرمز شده است؟
  • Assertion باریک و پیام شکست برای شروع عیب‌یابی کافی است؟
  • تعداد فراخوانی یا تعامل فقط وقتی Assert می‌شود که بخشی از قرارداد باشد؟

راهنمای Google Testing Blog درباره شکست‌های قابل‌اقدام توصیه می‌کند نام تست و پیام شکست اطلاعات لازم برای شروع بررسی را فراهم کنند. عبارت عمومی expected true, got false شاهد ضعیفی است.

استقلال، زمان و تکرارپذیری

  • هر تست وضعیت، Session و دادهٔ خودش را دارد و به ترتیب اجرا وابسته نیست؟
  • Clock، Random و شناسهٔ تولیدی قابل‌کنترل یا در شواهد ثبت شده‌اند؟
  • Wait ثابت با انتظار روی وضعیت قابل‌مشاهده جایگزین شده است؟
  • اجرا به‌صورت تکی، در Suite و موازی نتیجهٔ یکسان دارد؟
  • Retry خطا را پنهان نمی‌کند و تاریخچهٔ تلاش‌ها قابل‌مشاهده است؟

مستند بهترین‌روش‌های Unit Test مایکروسافت سرعت، استقلال، تکرارپذیری و Self-checking بودن را ویژگی‌های مهم تست واحد می‌داند و یادآوری می‌کند درصد Coverage به‌تنهایی کیفیت را اثبات نمی‌کند.

مرز Test Double و Fidelity

  • Stub/Mock/Fake دقیقاً برای چه ریسکی استفاده شده و چه چیزی را اثبات نمی‌کند؟
  • Request و Response به‌صورت معنایی Match می‌شوند یا Stub بیش از حد آسان پاسخ می‌دهد؟
  • نسخهٔ Contract یا روش کالیبراسیون با Provider واقعی مشخص است؟
  • Timeout، Retry، پاسخ ناقص و خطای احراز هویت متناسب با ریسک مدل شده‌اند؟

هرچه Double از رفتار واقعی دورتر باشد، تست ممکن است سبز اما بی‌اعتبار شود. مرور معماری تست‌پذیری نرم‌افزار و Testability Contract برای تعیین نقاط کنترل و مشاهده کمک می‌کند.

خوانایی و نگهداری

  • نام تست سناریو و نتیجه را بیان می‌کند و Arrange/Act/Assert دیده می‌شود؟
  • Abstraction نیت دامنه را روشن می‌کند یا فقط جزئیات را پشت Helper مبهم پنهان کرده است؟
  • کد تکراری واقعاً دانش مشترک است، یا استخراج آن تست را به Fixture سراسری کوپل می‌کند؟
  • Selectorها و APIها قرارداد پایدار دارند و جزئیات DOM یا پیاده‌سازی بی‌دلیل Assert نشده‌اند؟
  • تست به اندازهٔ کد تولید جدی گرفته شده و پیچیدگی اضافی ندارد؟

برای طراحی Driver، Page Object و مرزهای SOLID به راهنمای کد تست قابل نگهداری رجوع کنید. DRY هدف مطلق نیست؛ گاهی کمی تکرار، نیت دو سناریوی مستقل را خواناتر نگه می‌دارد.

ایمنی داده و عملیات

  • Secret در کد، Fixture، Screenshot، Trace یا گزارش ذخیره نشده است؟
  • دادهٔ شخصی حداقل، مصنوعی و دارای TTL است؟
  • پاک‌سازی فقط منابع دارای run_id خودش را حذف می‌کند و روی محیط گسترده عمل نمی‌کند؟
  • تست مخرب یا مالی در محیط و حساب مجاز اجرا می‌شود؟
  • در شکست میانی نیز Cleanup و حفظ شواهد ترتیب امن دارند؟

پایپ‌لاین و شواهد اجرا

  • Exit code واقعی Runner به Job می‌رسد و سبزی کاذب ایجاد نمی‌شود؟
  • نسخهٔ کد، Image، Browser، Dependency، Flag و Schema ثبت شده‌اند؟
  • Artifactهای شکست پیش از Teardown جمع‌آوری و اطلاعات حساس از آن‌ها حذف می‌شود؟
  • Timeout و Retry محدود، دلیل‌دار و در گزارش آشکارند؟
  • تست Quarantine شده Owner، دلیل و تاریخ انقضا دارد؟

برای اجرای این کنترل‌ها در MR می‌توانید از الگوی تست خودکار در GitLab CI و Pipeline قابل‌عیب‌یابی استفاده کنید.

مثال بازبینی کد Playwright

قبل: سبز، سریع و کم‌معنا

test('payment works', async ({ page }) => {
  await page.goto('/checkout');
  await page.locator('.pay-btn').click();
  await page.waitForTimeout(5000);
  expect(await page.locator('.success').isVisible()).toBe(true);
});

کامنت بازبین باید فراتر از «از timeout استفاده نکن» باشد. این تست به کلاس CSS وابسته است، انتظار ثابت دارد، فقط یک پیام را می‌بیند، داده/شناسه ندارد و موفقیت مالی را اثبات نمی‌کند. اگر UI پیام موفقیت را اشتباهی نشان دهد، تست سبز می‌ماند.

بعد: رفتار قابل‌مشاهده و شاهد دامنه

test('paid order creates one ledger entry', async ({ page, request }) => {
  const order = await createOrder({ amountRial: 1_000_000 });

  await page.goto(`/checkout/${order.id}`);
  await page.getByRole('button', { name: 'پرداخت' }).click();
  await completeSandboxPayment({ orderId: order.id });

  await expect(page.getByRole('status'))
    .toHaveText('پرداخت با موفقیت ثبت شد');

  const payment = await request.get(`/test-support/orders/${order.id}/payment`);
  expect(await payment.json()).toMatchObject({
    status: 'PAID', amountRial: 1_000_000, ledgerEntries: 1
  });
});

این مثال هنوز نیازمند Review امنیت endpoint پشتیبان و پاک‌سازی داده است، اما نیت، مبلغ ریالی، Selector کاربرمحور، انتظار خودکار و اثر مالی را روشن‌تر می‌کند. راهنمای رسمی Playwright نیز رفتار قابل‌مشاهده برای کاربر، جداسازی تست‌ها، Locatorهای کاربرمحور و Assertionهای auto-retrying را توصیه می‌کند.

چگونه کامنت بازبینی بنویسیم؟

کامنت مؤثر سه جزء دارد: مشاهده → ریسک یا شاهد → درخواست روشن. به کد و اثر آن اشاره کنید، نه به شخصیت نویسنده.

[MUST] این Assertion فقط نمایش پیام موفقیت را می‌سنجد. باگ PAY-۱۸۴ نشان داد UI می‌تواند موفق باشد ولی Ledger ثبت نشود. لطفاً وضعیت سفارش و تعداد Ledger entry را از نقطهٔ مشاهدهٔ مجاز Assert کن و اجرای قرمز روی نسخهٔ قبل از Fix را پیوست کن.

شدت کامنت را از ابتدا برچسب بزنید:

برچسب معنا آیا مانع تأیید است؟
[BLOCKER] ریسک انتشار، امنیت، از‌دست‌رفتن داده یا شاهد نامعتبر بله؛ نیازمند اصلاح یا پذیرش رسمی مالک ریسک
[MUST] استاندارد یا رفتار لازم این تغییر رعایت نشده بله
[SHOULD] بهبود مهم ولی غیرمسدودکننده در این تغییر معمولاً خیر؛ تصمیم ثبت شود
[QUESTION] نیاز به روشن‌شدن فرض یا نیت تا پاسخ معتبر، تصمیم باز می‌ماند
[NIT] نکتهٔ جزئی و ترجیحی خیر

راهنمای کامنت Code Review گوگل نیز توضیح دلیل، احترام، تفکیک شدت و تمرکز بر کد را پیشنهاد می‌کند. از سؤال‌های اتهامی مانند «چرا همیشه تست Flaky می‌نویسی؟» پرهیز کنید؛ بنویسید «این Fixture وضعیت مشترک دارد و اجرای موازی دوم شکست خورد؛ لطفاً داده را per-test بساز.»

اختلاف نظر را با شاهد حل کنید

  1. نقطهٔ اختلاف را به Basis، ریسک و مشاهدهٔ فنی برگردانید.
  2. اگر داده کم است، یک آزمایش کوچک، اجرای هدفمند یا نمونهٔ تولید طراحی کنید.
  3. بین الزام، پیشنهاد و سلیقه تمایز بگذارید؛ Style Guide را مرجع کنید.
  4. اگر گفت‌وگوی نوشتاری فرسایشی شد، جلسهٔ کوتاه برگزار و نتیجه را مکتوب کنید.
  5. در بن‌بست، مالک فنی/ریسک تصمیم می‌گیرد؛ Gap، Owner و تاریخ بازنگری ثبت می‌شود.

«سابقه بیشتر» به‌تنهایی شاهد نیست. همین‌طور، رأی اکثریت نمی‌تواند یک الزام امنیتی یا ناسازگاری قراردادی را حذف کند. اختلاف سالم باید فرض‌ها را آشکارتر کند، نه فقط صف تأیید را طولانی‌تر.

Review چگونه کیفیت و ثبات را بهبود می‌دهد؟

بازبینی، کیفیت را تضمین نمی‌کند؛ سه سازوکار قابل‌دفاع برای بهبود دارد:

  • کاهش Gap شناخته‌شده: نگاه دوم، ریسک، مرز و فرض فراموش‌شده را پیش از ادغام آشکار می‌کند.
  • بهبود تشخیص: Oracle دقیق و پیام قابل‌اقدام، زمان عیب‌یابی را کم می‌کند.
  • پخش دانش: تصمیم دامنه و الگوی فنی در Artifact ماندگار می‌شود و Bus Factor کاهش می‌یابد.

اثر واقعی وابسته به کیفیت فرایند است. Approval کور، صف طولانی و کامنت‌های سلیقه‌ای می‌توانند سرعت و اعتماد تیم را بدتر کنند. رهبری تضمین کیفیت و مالکیت همگانی توضیح می‌دهد چگونه مسئولیت مشترک را بدون مبهم‌کردن پاسخ‌گویی بسازید.

ابزارها را بر اساس نقش انتخاب کنید

نیاز نمونه ابزار کنترل مهم
Diff، گفت‌وگو و Approval GitLab، GitHub، Bitbucket CODEOWNERS، وضعیت کامنت، Scope بازبین، Audit trail
مدیریت تست و Traceability TestRail، Xray، Zephyr نسخهٔ Basis، مالک، ارتباط با اجرا و Defect
کنترل ماشینی Linter، Compiler، SAST، Secret Scanner نسخهٔ Rule، Baseline، خط‌مشی False Positive
شواهد اجرا CI، Report، Log، Trace شناسهٔ اجرا، نگه‌داری، Redaction و دسترسی

ابزار مدیریت تست برای سناریوی دستی و Git برای کد مناسب‌اند، اما پیوند بین آن‌ها باید پایدار باشد. کپی‌کردن چند نسخه از انتظار در Ticket، Sheet و کد، Drift می‌سازد. یک Source of Truth تعریف کنید و بقیه را با شناسه و نسخه به آن وصل کنید.

استفاده از هوش مصنوعی در بازبینی تست

مدل زبانی می‌تواند Diff را خلاصه کند، سؤال مرزی پیشنهاد دهد یا الگوهای تکراری را بیابد؛ اما پیشنهاد آن شاهد و Approval نیست. ممکن است API قدیمی، رفتار خیالی یا اصلاح ناامن بسازد.

  • کد، Secret، دادهٔ شخصی و Log حساس را بدون مجوز به سرویس بیرونی نفرستید.
  • نسخهٔ Framework و لینک مستند رسمی هر پیشنهاد را بررسی کنید.
  • تغییر تولیدشده را مانند کد انسانی اجرا و Review کنید.
  • مالک انسانی پاسخ‌گوی Oracle، Risk acceptance و ادغام باقی می‌ماند.
  • نرخ پذیرش پیشنهاد AI را معیار کیفیت ندانید؛ Defect yield و پیامد را بسنجید.

معیارهای سلامت فرایند بازبینی

تعداد کامنت، تعداد Approval و سرعت خام، به‌سادگی بازی داده می‌شوند. داشبورد متوازن‌تری بسازید:

  • زمان تا اولین بازبینی و Cycle time، تفکیک‌شده بر اساس سطح ریسک؛
  • نرخ یافتن مشکل مسدودکننده با دستهٔ Oracle، داده، امنیت، پوشش یا پایداری؛
  • رخدادهای سیستم تست پس از ادغام: Flaky، سبزی کاذب، شکست Cleanup یا نشت Secret؛
  • نرخ بازگشایی و رفت‌وبرگشت Review و علت آن؛
  • تمرکز بار روی چند بازبین و سن صف انتظار؛
  • عمر Gap پذیرفته‌شده و Quarantineهای منقضی؛
  • میانگین زمان عیب‌یابی شکست تست و درصد شکست‌های قابل‌بازتولید؛
  • Defect escaped مرتبط با تستی که بازبینی شده، همراه با Retro بدون سرزنش.

هدف معیار، یافتن گلوگاه سیستم است. اگر Cycle time بالا رفت، الزاماً بازبین کند نیست؛ شاید بسته ناقص، تغییر بیش از حد گسترده یا مالکیت حوزه نامشخص باشد.

خطاهای رایج در Peer Review تست

  • LGTM بدون اعلام Scope یا مشاهدهٔ شواهد؛
  • تمرکز بر فاصله و نام‌گذاری در حالی که Oracle اشتباه است؛
  • الزام تعداد ثابت Reviewer برای همهٔ تغییرها؛
  • جلسه برای هر مورد یا برعکس، حل اختلاف پیچیده فقط با Comment؛
  • یکی‌گرفتن Coverage بالا با پوشش ریسک؛
  • تأیید تستی که هیچ Negative proof ندارد؛
  • DRY افراطی و Fixtureهای مشترکِ پنهان‌کنندهٔ نیت؛
  • Mock دقیقاً مطابق انتظار تست، بدون کالیبراسیون با Provider؛
  • Retry نامحدود، Quarantine بی‌مالک و بستن کامنت بدون پاسخ؛
  • ذخیره Secret یا PII در Screenshot، Trace و Fixture؛
  • حل اختلاف با عنوان شغلی به جای Basis و Evidence؛
  • استفاده از تعداد کامنت به‌عنوان KPI بازبین؛
  • ادغام Refactor بزرگ، تغییر رفتار و Format در یک Diff؛
  • پذیرش پیشنهاد AI بدون بررسی نسخه، اجرا و مسئول انسانی؛
  • اعلام اینکه Review «همهٔ خطاها» را حذف یا کیفیت را تضمین می‌کند.

برنامهٔ ۳۰روزه برای استقرار بازبینی ریسک‌محور

هفتهٔ اول: Baseline و توافق واژگان

ده تغییر اخیر را بررسی کنید: زمان صف، انواع کامنت، Flaky پس از ادغام و Gapهای تکراری را ثبت کنید. سپس تعریف مشترک Basis، Oracle، Evidence، Blocker و Risk owner را بنویسید.

هفتهٔ دوم: قالب و پایلوت

قالب بستهٔ بازبینی و برچسب شدت را روی یک تیم یا جریان متوسط اجرا کنید. Lint، Secret scan و Build را از فهرست انسانی خارج و خودکار کنید. دو نمونهٔ خوب و بد را در Wiki نگه دارید.

هفتهٔ سوم: سطح‌بندی و مالکیت

ماتریس ریسک را به CODEOWNERS یا سیاست Approval وصل کنید. برای پرداخت، امنیت، دیتابیس و دسترس‌پذیری متخصص و جانشین مشخص کنید. SLA پاسخ را با توجه به سطح ریسک و ظرفیت واقعی توافق کنید.

هفتهٔ چهارم: اندازه‌گیری و اصلاح

یک Retrospective بدون سرزنش برگزار کنید. ببینید کدام سؤال نقص واقعی یافت، کدام کنترل فقط نویز ساخت و بار روی چه کسانی افتاد. چک‌لیست را کوتاه‌تر و دقیق‌تر کنید؛ کنترل بی‌اثر را صرفاً به دلیل عادت نگه ندارید.

چک‌لیست نهایی پیش از Approval

  1. ریسک، کاربر متأثر و Basis نسخه‌دار مشخص است.
  2. سطح بازبینی و افراد واجد صلاحیت با نوع تغییر هم‌خوان‌اند.
  3. داده، واحد، Locale، زمان و وضعیت اولیه بدون ابهام‌اند.
  4. Oracle نتیجهٔ مهم و اثر جانبی را در نقطهٔ درست می‌بیند.
  5. شاهد وجود دارد که تست با خرابی هدفمند قرمز می‌شود.
  6. تست مستقل، تکرارپذیر و برای اجرای موازی آماده است.
  7. مرز Double، Contract و محیط واقعی روشن است.
  8. Secret/PII محافظت و Cleanup محدود و امن است.
  9. پیام شکست، Run identity و Artifactها عیب‌یابی را ممکن می‌کنند.
  10. هر کامنت شدت، دلیل و درخواست روشن دارد.
  11. Gap باقی‌مانده Owner و تاریخ بازنگری دارد.
  12. Scope تأیید بازبین و تصمیم نهایی در سیستم ثبت شده است.

پرسش‌های متداول

آیا همهٔ تست‌کیس‌ها و کدهای تست باید Peer Review شوند؟

همهٔ تغییرها باید حداقل خودبازبینی و کنترل ماشینی متناسب داشته باشند، اما عمق Review انسانی یکسان نیست. تغییر کم‌ریسک و مکانیکی می‌تواند مسیر سبک داشته باشد؛ تغییر پرداخت، امنیت، داده یا Oracle مشترک به بازبین متخصص و شواهد قوی‌تر نیاز دارد. سیاست را بر پیامد خطا بنا کنید.

برای بازبینی تست چند Reviewer لازم است؟

عدد جهانی وجود ندارد. معیار، پوشش صلاحیت و استقلال لازم برای ریسک است. یک بازبین دامنه برای تغییر متوسط ممکن است کافی باشد؛ تغییر چندحوزه‌ای پرریسک می‌تواند بازبین امنیت، دیتابیس یا مالک کسب‌وکار بخواهد. تعداد امضا را جایگزین کیفیت بررسی نکنید.

چگونه ثابت کنیم یک تست خودکار واقعاً خطا را می‌گیرد؟

تست را روی نسخهٔ معیوب اجرا کنید، Fix را موقتاً برگردانید، Mutation هدفمند بسازید یا Incident را بازتولید کنید. باید به دلیل مورد انتظار قرمز شود و پیام آن قابل‌اقدام باشد. اجرای سبز پس از Fix فقط نیمهٔ دوم شاهد است.

آیا Code Review جای اجرای تست یا تست اکتشافی را می‌گیرد؟

خیر. Review یک فعالیت ایستا برای یافتن نقص طراحی، فرض و Oracle است؛ اجرای تست رفتار واقعی را می‌سنجد و Exploration ریسک‌های ناشناخته را کشف می‌کند. این سه مکمل‌اند و هرکدام مرز اثبات متفاوتی دارند.

با اختلاف بین نویسنده و بازبین چه کنیم؟

بحث را به Basis، ریسک و شاهد برگردانید، الزام را از سلیقه جدا و در صورت نیاز آزمایش کوچکی اجرا کنید. اگر توافق حاصل نشد، مالک فنی یا ریسک تصمیم می‌گیرد. نتیجه، Gap، Owner و تاریخ بازنگری باید در همان MR یا رکورد تست ثبت شود.

جمع‌بندی: Review یک تصمیم شواهدمحور است

بازبینی مؤثر از سؤال «آیا قالب تست‌کیس کامل است؟» فراتر می‌رود و می‌پرسد «این تست کدام ریسک را، با کدام Oracle و چه شاهدی کاهش می‌دهد؟» سطح بازبینی را با ریسک تنظیم کنید، کار قطعی را به ماشین بسپارید، از انسان برای داوری معنایی استفاده کنید و Scope تصمیم را ثبت کنید. آن‌وقت Peer Review از صف امضا به یک حلقهٔ یادگیری و کنترل واقعی تبدیل می‌شود.

برای شروع، فقط یک تغییر پرکاربرد را انتخاب کنید: بستهٔ هشت‌قسمتی شواهد را بسازید، شدت Commentها را برچسب بزنید و یک Negative proof مطالبه کنید. پس از دو هفته، اثر آن را با زمان عیب‌یابی، Flaky پس از ادغام و Gapهای کشف‌شده بسنجید؛ نه با تعداد کامنت‌ها.

دیدگاهتان را بنویسید