تست رگرسیون: چرا هر باگ باید یک تست بشود

جملهای که هیچ تیمی دوست ندارد از مشتری بشنود: «این مشکل که قبلاً درست شده بود».
باگ برگشته، دو بار هزینه دارد — یک بار برای رفع دوباره، و یک بار برای چیزی که گرانتر است: اعتماد. مشتریای که یک بار این را تجربه کرده، از آن به بعد دربارهٔ هر تحویلی سؤال دارد.
تست رگرسیون دقیقاً برای همین یک کار است. نه برای پیدا کردن باگ جدید — برای اطمینان از اینکه چیزی که کار میکرد، هنوز کار میکند.
قاعدهای که کل مجموعه را میسازد
هر باگی که در تولید پیدا میشود، پیش از رفع، یک تست میشود.
ترتیب مهم است: اول تست بنویسید و ببینید قرمز میشود. اگر قرمز نشد، شما باگ را نفهمیدهاید و رفعتان هم احتمالاً درست نیست. بعد رفع کنید تا سبز شود.
این سادهترین رویهای است که میشناسیم و بیشترین اثر را دارد، به سه دلیل:
مجموعهٔ تست شما به سمت چیزهایی میرود که واقعاً میشکنند. بهجای تصمیم انتزاعی دربارهٔ «چه چیزی را تست کنیم»، واقعیت تولید تصمیم میگیرد.
پوشش، معنادار میشود. درصد پوشش تست عددی است که بهراحتی گمراه میکند؛ اما تستی که از یک خرابی واقعی آمده، ارزشش ثابتشده است.
نشان میدهد کجا تمرکز باگ هست. اگر بیست تست رگرسیون همه از یک ماژول آمده باشند، آن ماژول جایی است که بازآرایی باید از آن شروع شود.
اما تست، تنها چیزی نیست که باید بسازید
باگ رگرسیون یعنی چیزی که قبلاً درست شده بود دوباره خراب شد. سه راه برای این وجود دارد و فقط اولی با تست حل میشود:
رفع، برگشت خورده. ادغام بد، بازگردانی اشتباهی، یا شاخهای که قدیمی بوده. تست این را میگیرد.
رفع، ناقص بوده. علت اصلی برطرف نشده و باگ از مسیر دیگری برگشته. تست همان مسیر قبلی را میگیرد و مسیر جدید را نه. جوابش سؤال ریشه است، نه تست بیشتر.
رفع، جای دیگری را شکسته. تغییری که یک چیز را درست کرد و چیز دیگری را خراب. اینجا مجموعهٔ رگرسیون بهعنوان یک کل کار میکند، نه یک تست خاص.
کدام لایه؟ ارزانترین لایهای که باگ را میگیرد
وسوسهٔ رایج این است که هر باگ گزارششده از رابط کاربری، به یک تست سرتاسری تبدیل شود. این راه، مجموعهای میسازد که در دو سال به یک بار سنگین و شکننده تبدیل میشود.
قاعده: پایینترین لایهای که خرابی را نشان میدهد.
باگ محاسبهٔ تخفیف که از طریق صفحهٔ سبد گزارش شده، در نود درصد موارد یک تست واحد روی تابع محاسبه است — سریع، پایدار، و دقیقاً همان چیزی که شکسته بود.
تست سرتاسری را برای چیزی نگه دارید که فقط در سطح سرتاسری میشکند: توالی مراحل، وضعیت نشست، مسیر پرداخت. تفکیک لایهها در استراتژی تست آمده.
مسئلهٔ اصلی: مجموعهای که بزرگ میشود
مجموعهٔ رگرسیون بهطور طبیعی فقط رشد میکند. سه سال بعد، هزار تست دارید که بیست دقیقه طول میکشند و پنجاهتایشان گاهی بیدلیل قرمز میشوند.
آن لحظه، لحظهای است که تیم شروع میکند به نادیده گرفتن نتیجه — و مجموعهٔ تستی که نادیده گرفته میشود از نداشتنش بدتر است، چون هزینهٔ نگهداری دارد و اطمینان کاذب میدهد.
چهار کار که این را عقب میاندازد:
تست ناپایدار، همان روز. تستی که گاهی قرمز است یا همان روز درست میشود یا حذف. نگهداشتنش با این توجیه که «معمولاً کار میکند» شروع فروپاشی اعتماد است. منشأ بیشترشان دادهٔ تست است.
تقسیم به دو مجموعه. یک مجموعهٔ سریع (زیر پنج دقیقه) که در هر تغییر اجرا میشود، و یک مجموعهٔ کامل که شبانه یا پیش از انتشار. تفکیکش بخشی از طراحی خط لوله است.
حذف تستهای بیفایده. تستی که سه سال هیچوقت قرمز نشده و کد زیرش هم عوض نشده، احتمالاً ارزشی اضافه نمیکند. حذف تست، بدعت نیست؛ نگهداری است.
تست را با کد بازآرایی کنید. تست هم کد است و همان بدهی را جمع میکند. مجموعهای که هر تغییر کوچک صد تست را میشکند، مجموعهای است که به جزئیات پیادهسازی چسبیده، نه به رفتار.
و تست دستی، که جایش را از دست نداده
اتوماسیون همهچیز را نمیگیرد. سه چیز که در عمل دستی میمانند:
تست اکتشافی. یک نفر با ذهن باز سامانه را میگردد. چیزهایی پیدا میکند که هیچ تست خودکاری دنبالشان نمیگشت، چون تست خودکار فقط چیزی را میسنجد که کسی به آن فکر کرده.
بررسی ظاهر و چیدمان. بهخصوص در فارسی: راستبهچپ، متن بلند که چیدمان را میشکند، ترکیب عدد فارسی و لاتین. جزئیاتش در وب فارسی.
تست پذیرش با کاربر واقعی. که سؤال متفاوتی میپرسد: نه «آیا درست کار میکند» بلکه «آیا این همان چیزی است که خواسته بودیم».
معیاری که میگوید کار میکند
یک عدد را دنبال کنید: نسبت باگهای کشفشده پیش از انتشار به باگهای کشفشده در تولید.
اگر این نسبت بالا میرود، مجموعهٔ تست دارد کارش را انجام میدهد. اگر پایین میآید — یعنی سهم بیشتری از باگها را مشتری پیدا میکند — تعداد تستها مهم نیست؛ تستها چیز درستی را نمیسنجند.
این تنها سنجهٔ تستی است که سراغ داریم و گمراهکننده نیست. درصد پوشش، برخلافش، با بیست تست بیارزش هم بالا میرود.