۶۹ تست نوشته شده توسط هوش مصنوعی یک ماژول پایتون را با موفقیت پشت سر گذاشتند، با این حال یک آزمایش نشان داد که رویکرد هدفمند در تولید تست، ۴۴ مورد از ۵۳ خطای تزریق‌شده را شناسایی کرده است. این نمونه اولیه که طی یک آخر هفته ساخته شد، یک ضعف اساسی در تست‌نویسی فعلی توسط مدل‌های زبانی بزرگ (LLM) را اثبات می‌کند: بدون یک حلقه بازخورد که بررسی کند آیا یک تست واقعاً در برابر یک نقص شناخته‌شده شکست می‌خورد یا خیر، مجموعه تست‌های تولیدشده می‌تواند بی‌نقص به نظر برسد در حالی که دقیقاً همان باگ‌هایی را که قرار بود فاش کند، از دست می‌دهد.

چرا این آزمایش اهمیت دارد

تولید خودکار تست نوید می‌دهد که شکاف بین کد و پوشش (coverage) را کاهش دهد، به‌ویژه با توجه به اینکه توسعه‌دهندگان برای نوشتن تست‌های واحد (unit tests) به LLMها تکیه می‌کنند. اکثر بنچمارک‌های عمومی، موفقیت را با اندازه‌گیری پوشش خط (line coverage) ارزیابی می‌کنند؛ یعنی اینکه آیا هر خط از کد در طول اجرای تست اجرا می‌شود یا خیر. این معیار می‌تواند گمراه‌کننده باشد: یک خط ممکن است اجرا شود بدون اینکه تست هرگز رفتار صحیح را تأیید (assert) کند. تست جهش (Mutation testing) این نقطه کور را با خراب کردن عمدی کد منبع (مثلاً معکوس کردن یک مقایسه، حذف یک دستور و غیره) و مشاهده اینکه آیا تست‌های موجود تغییر را تشخیص می‌دهند یا خیر، پر می‌کند. اگر نسخه جهش‌یافته همچنان با موفقیت اجرا شود، یعنی مجموعه تست یک نقص واقعی را از دست داده است.

این آزمایش سه روش برای پرسش (prompting) از یک LLM جهت تولید تست را با هم مقایسه کرد:

  • Bulk prompting (پرسش دسته‌ای) – یک درخواست واحد برای «تست‌های بیشتر»، ۶۹ تست تولید کرد که همگی کد تغییرنیافته را با موفقیت پشت سر گذاشتند، اما تنها ۹ مورد از ۵۳ جهش را شناسایی کردند.
  • One-test-per-call, untargeted (تک‌تست در هر فراخوانی، بدون هدف‌گیری) – از مدل بارها برای تولید یک تست واحد بدون راهنمایی درباره خطاها خواسته شد؛ این روش تنها ۲ جهش را شناسایی کرد.
  • Targeted prompting with a mutation-testing gate (پرسش هدفمند با دروازه تست جهش) – مدل هر جهشِ شناسایی‌نشده را مشاهده کرد و از او خواسته شد تستی بنویسد که در کد جهش‌یافته شکست بخورد اما در نسخه سالم با موفقیت اجرا شود. این رویکرد منجر به تولید ۴۴ تست شناسایی‌کننده شد.

تفاوت فاحش — ۴۴ در مقابل ۹ یا ۲ — نشان می‌دهد که یک حلقه بازخورد محدود و خطا-محور می‌تواند قدرت یافتن نقص در تست‌های تولیدشده توسط هوش مصنوعی را به طرز چشمگیری بهبود بخشد.

نحوه عملکرد دروازه تست جهش

  1. تزریق جهش‌ها (Inject mutations) – ابزار اجرا (harness) تغییرات کوچک و سیستماتیکی در منبع اصلی ایجاد می‌کند (مثلاً معکوس کردن یک شرط، حذف یک خط). هر جهش نشان‌دهنده یک باگ بالقوه است.
  2. اجرای مجموعه تست فعلی – اگر مجموعه تست همچنان با موفقیت اجرا شود، یعنی جهش شناسایی نشده است.
  3. پرسش از LLM – مدل جهش خاص را دریافت می‌کند و از او خواسته می‌شود تستی تولید کند که در کد جهش‌یافته شکست بخورد اما در کد اصلی موفق باشد.
  4. اعتبارسنجی تست جدید – تست را تنها در صورتی نگه دارید که در کد سالم با موفقیت اجرا شود و در نسخه جهش‌یافته شکست بخورد.
  5. تکرار – این مراحل را برای هر جهش شناسایی‌نشده تکرار کنید.

این مرحله اعتبارسنجی، همان «دروازه» است. این مرحله هر تستی را که حساسیت نسبت به خطای هدف را نشان ندهد، فیلتر می‌کند و تضمین می‌کند که هر تستِ حفظ‌شده، ارزش اثبات‌شده‌ای در شناسایی خطا داشته باشد.

درس‌هایی از اعداد

  • کدهای دست‌نیافتنی عامل اصلی خطاهای شناسایی‌نشده هستند – در پایگاه‌های کد بالغ، بسیاری از خطوط هرگز توسط تست‌های موجود اجرا نمی‌شوند. آزمایش نشان داد که بیشتر جهش‌های شناسایی‌نشده در چنین نواحی غیرقابل‌دسترسی قرار داشتند.
  • دروازه، تست‌های معتبر را به دلیل اشتباه حذف می‌کند – هر تستِ رد شده، در کد سالم با موفقیت اجرا شده بود؛ دروازه آن‌ها را حذف کرد چون در برابر آن جهش خاص شکست نخوردند. یک تست می‌تواند کاملاً درست باشد اما با خطای مورد بررسی بی‌ارتباط باشد.
  • تست‌های هدفمند بسیار خاص هستند – از ۴۴ تست موفق، ۳۶ مورد دقیقاً تنها یک جهش را شناسایی کردند. مجموعه تست به جای مجموعه‌ای از تأییدهای گسترده، به مجموعه‌ای از بررسی‌های بسیار محدود تبدیل شد که پرسش‌هایی را در مورد قابلیت نگهداری و بیش‌برازش (over-fitting) ایجاد می‌کند.

آنچه نتایج پوشش نمی‌دهند

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

پیامدها برای تست‌نویسی مبتنی بر هوش مصنوعی

  • اهمیت معیارها – تکیه صرف بر پوشش خطی (line coverage) می‌تواند احساس امنیت کاذبی ایجاد کند. تست جهش (Mutation testing) معیاری رفتار-محورتر ارائه می‌دهد و ادغام آن در حلقه ارزیابی می‌تواند نقاط کور را در مراحل اولیه آشکار کند.
  • حلقه‌های بازخورد خروجی را بهبود می‌بخشند – بهبود چشمگیر حاصل از این دروازه (gate) تأکید می‌کند که مدل‌های زبانی بزرگ (LLMs) به جای تولید تک‌مرحله‌ای (one-shot)، از پرامپت‌های تکرارشونده و اصلاحی بهره می‌برند.
  • شفافیت ابزار ضروری است – نویسنده متوجه ۱۱ باگ در خودِ چارچوب اندازه‌گیری (measurement harness) شد که در ابتدا نرخ موفقیت گزارش‌شده را بیش از حد واقعی نشان می‌داد. انتشار چارچوب در کنار نتایج، به جامعه اجازه می‌دهد تا خط لوله ارزیابی را بازرسی و بهبود بخشند.

آنچه باید در ادامه دنبال کرد

  • خط لوله‌های ترکیبی – ترکیب تولید انبوه تست برای پوشش گسترده با اصلاح هدفمند مبتنی بر جهش برای عمق بیشتر، می‌تواند مجموعه‌ای متوازن ایجاد کند که هم کد را پوشش داده و هم رفتار را تأیید کند.
  • تأیید خودکار چارچوب – با پذیرش تست جهش به عنوان یک معیار (benchmark) توسط پژوهشگران بیشتر، ابزارهایی که مجموعه‌های جهش و خط لوله‌های اجرای خود را خودکار تأیید می‌کنند، برای جلوگیری از خطاهای اندازه‌گیری پنهان، حیاتی خواهند شد.
  • مطالعات تعمیم‌پذیری – کارهای آینده باید بررسی کنند که آیا تست‌های تولید شده از طریق این دروازه، هنگام اعمال بر باگ‌های دیده‌نشده یا در محیط‌های عملیاتی (production)، اثربخشی خود را حفظ می‌کنند یا خیر؛ این امر به نگرانی در مورد محدود بودن (narrowness) پاسخ می‌دهد.

نتیجه‌گیری

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