اگر امروز به گزارشهای سبز رنگ پوشش کد (Code Coverage) در پروژههایتان اعتماد میکنید، احتمالاً در حال تماشای یک نمایش جادویی هستید. بسیاری از تستهای تولیدشده توسط هوش مصنوعی، خطوط کد را اجرا میکنند اما هرگز بررسی نمیکنند که آیا خروجی واقعاً درست است یا خیر. BrassCoders هشدار میدهد که تستهای تولیدشده توسط AI اغلب ۹۰٪ از یک کدبیس را اجرا میکنند، بدون اینکه در واقع بررسی کنند آیا نتایج صحیح هستند یا خیر؛ موضوعی که باعث میشود باگهای حیاتی شناسایینشده باقی بمانند.
این وضعیت شبیه نگهبانی است که تمام راهروهای ساختمان را میپیماید اما هرگز چک نمیکند که آیا درها واقعاً قفل شدهاند یا نه. اکثر تستهای نوشته شده توسط AI امروزه به همین شکل عمل میکنند. آنها با اجرای خطوط کد، گزارش پوشش را ارضا میکنند، اما در تأیید (Assert) اینکه خروجی معتبر است، شکست میخورند.
این شکاف بین «اجرا» و «تأیید»، یک مشکل سیستماتیک در توسعههای مبتنی بر مدلهای زبانی بزرگ (LLM) است. این چالش در واقع ریشه در نیاز مبرم عاملهای کدنویس به شواهد اجرایی در برابر اعتماد کورکورانه دارد تا توهمات مدل در زمان تولید تست حذف شود. بر اساس مطالعهای در سال ۲۰۲۳ روی تستهای واحد تولیدشده توسط ChatGPT، تنها ۲۴.۸٪ از تستها بدون خطای اجرا runnable بودند. نگرانکنندهتر اینکه ۱۷.۳٪ از تستها با موفقیت کامپایل شدند اما به دلیل اینکه مدل «ادعاهای» (Assertions) غلطی نوشته بود، در شناسایی خطا شکست خوردند. در این ارزیابی تجربی روی ۱۰۰۰ تست، گزارش شد که اگرچه ۴۲.۱٪ کامپایل شدند، اما کمتر از یکچهارم آنها بهطور تمیز اجرا شدند.
توهم پوشش
ابزارهای سنتی مانند coverage.py فقط نظارت میکنند که کدام بخشهای کد اجرا شدهاند. مستندات این ابزار صراحتاً میگوید که این ابزار فقط بخشهایی از کد را شناسایی میکند که میتوانستند اجرا شوند اما نشدند، و هیچ ادعایی درباره این موضوع نمیکند که آیا کد اجراشده از نظر رفتاری بررسی شده است یا خیر.
تصور کنید تستی تابع parse_date(input) را فراخوانی کند اما هیچ چیزی را بررسی (Assert) نکند. این تست تمام خطوط داخل تابع را اجرا میکند و گزارش پوشش کد، تمام آنها را به عنوان «پوشش داده شده» ثبت میکند. اما اگر تابع تاریخ غلط، نوع داده اشتباه یا مقدار None برگرداند، تست همچنان «پاس» میشود.
پروژه تست جهش (Mutation Testing) با نام PIT صراحتاً اشاره میکند که معیارهای سنتی پوشش، فقط اندازهگیری میکنند که کدام کد اجرا شده است و بررسی نمیکنند که آیا تستها واقعاً قادر به شناسایی نقصها در آن کد هستند یا خیر.
پژوهشی توسط اینوزمتسوا و هولمز که در مقاله ICSE ۲۰۱۴ منتشر شد، ۳۱,۰۰۰ مجموعه تست را در ۵ سیستم با مجموع ۷۲۴,۰۰۰ خط کد تحلیل کرد. آنها دریافتند که وقتی تعداد موارد تست ثابت نگه داشته شود، تنها یک همبستگی پایین تا متوسط بین درصد پوشش و قدرت واقعی یک مجموعه تست در شناسایی خطاها وجود دارد. نتیجهگیری مستقیم آنها این بود: پوشش کد برای یافتن بخشهای «کمتست شده» مفید است، اما نباید به عنوان یک هدف کیفی (Quality Target) استفاده شود.
در این پژوهش مشخص شد که پوشش شاخهای (Branch Coverage) سیگنال بهتری نسبت به پوشش ساده دستورات (Statement Coverage) ارائه نمیدهد. در مقابل، مطالعهای توسط ژانگ و مصباح با عنوان «همبستگی شدید ادعاها با اثربخشی مجموعه تست»، ۶,۷۰۰ مجموعه تست شامل ۲۴,۰۰۰ ادعا را در ۵ پروژه واقعی جاوا بررسی کرد. آنها دریافتند که تعداد ادعاها — یعنی همان چکهای واقعی برای صحت خروجی — بهشدت با اثربخشی مجموعه تست در ارتباط است.
شکافهای عملکردی AI
شرکت BrassCoders تستهای AI را بهطور پیشفرض «غنی از پوشش اما فقیر در ادعا» میداند. عملکرد مدلهای زبانی بسته به محیط بهشدت تغییر میکند. طبق یافتههای سیدیق و همکارانش، مدل Codex در بنچمارک HumanEval به پوشش بیش از ۸۰٪ رسید، اما در مجموعه دادههای واقعی SF110، این عدد به زیر ۲٪ سقوط کرد. این تفاوت عملکردی نشاندهنده شکاف عمیق میان صحتِ پیادهسازی تکتک توابع و صحتِ کلی سیستم در خروجیهای عاملهای کدنویس است.
برخی از «بوی بد» (Test Smells) رایج در خروجیهای AI عبارتند از:
- تستهای خالی: تستهایی که کد را اجرا میکنند اما هیچ ادعایی ندارند؛ این تستها پوشش را بالا میبرند اما هیچ چیزی را بررسی نمیکنند.
- ادعاهای تکراری: تکرار یک بررسی مشابه برای متورم کردن گزارش بدون افزودن لایه تأیید واقعی.
حتی ابزارهای تخصصی مثل TestPilot هم میتوانند گمراهکننده باشند. در مطالعه سال ۲۰۲۴ IEEE Transactions on Software Engineering روی ۲۵ بسته npm، این ابزار به میانگین پوشش ۷۰.۲٪ برای دستورات رسید. رسیدن به عدد، تنها کاری است که این مولدها در آن مهارت دارند و دقیقاً به همین دلیل است که اعداد آنها جذاب به نظر میرسند.
اندازهگیری تأیید واقعی
برای مقابله با این مشکل، BrassCoders استفاده از تست جهش (Mutation Testing) را به عنوان بررسی توصیه میکند که پوشش کد قادر به انجام آن نیست. یک ابزار جهش، نقصهای کوچکی را در کد میکارد — مانند تغییر یک علامت مقایسهای یا تغییر یک مقدار ثابت — و سپس مجموعه تست را اجرا میکند تا گزارش دهد چه تعداد از این نقصها توسط تستها شناسایی شدهاند.
جاست و همکارانش در پژوهش خود با عنوان «آیا جهشها جایگزین معتبری برای نقصهای واقعی در تست نرمافزار هستند؟»، ثابت کردند که شناسایی جهشها یک جایگزین آماری معتبر برای شناسایی خطاهای واقعی است. آنها ۳۵۷ خطای واقعی را در ۳۲۱,۰۰۰ خط کد مطالعه کردند و دریافتند که این همبستگی مستقل از درصد پوشش کد وجود دارد.
ابزارهای پیشنهادی برای این کار:
- PIT: ابزار مرجع برای محیط JVM.
- mutmut: ابزار جهش برای پروژههای پایتون.
- Cosmic Ray: گزینهای قدرتمند و مستحکم دیگر برای پایتون.
اگر یک مجموعه تست نوشته شده توسط AI نتواند تقریباً هیچ جهشی را شناسایی (Kill) نکند، فارغ از اینکه درصد پوشش کد چقدر باشد، عملاً بیفایده است.
نقش تحلیل ایستا
تحلیل ایستا (Static Analysis) سیگنالی مستقل ارائه میدهد که به اجرای تست وابسته نیست. BrassCoders کدها را برای شناسایی الگوهایی مثل SQL Injection یا بازسازی ناامن دادهها (Unsafe Deserialization) اسکن میکند، فارغ از اینکه مجموعه تست آن خطوط را پوشش داده است یا خیر.
این یعنی یک گزارش سبز و با پوشش بالا نمیتواند یک آسیبپذیری را از چشم اسکنرهای ایستا پنهان کند. یک بررسی تحلیل ایستا، یک آسیبپذیری واقعی را علامتگذاری میکند، چه مجموعه تست آن خط را پوشش داده باشد و چه نداده باشد. با جداسازی اندازهگیری تستها از اندازهگیری کد، توسعهدهندگان دید صادقانهای از ریسکهای خود پیدا میکنند.
ابزار BrassCoders تستهای شما را اجرا یا نمره نمیدهد؛ بلکه کد را برای یافتن الگوهای خطایی که دستیارهای AI معمولاً وارد میکنند، میخواند. این ابزار روی فایلی که هیچ تستی ندارد و فایلی که ۱۰۰٪ پوشش دارد، به یک نتیجه یکسان میرسد. این ابزار تطبیقهای الگو را بهصورت YAML خروجی میدهد تا یک دستیار AI بتواند در بستر متن تصمیم بگیرد کدام مورد اهمیت دارد.
دیگر به درصد پوششی که دستیار AI شما ارائه میدهد اعتماد نکنید. از تست جهش برای تأیید ادعاهای خود و از تحلیل ایستا برای یافتن باگهایی که مجموعههای تست توخالی از دست میدهند، استفاده کنید. برای جزئیات بیشتر، به شاخص تحقیقات کیفیت تست AI در BrassCoders مراجعه کنید. BrassCoders به عنوان یکی از ۱۲ اسکنر در هر کامیت، کد شما را برای یافتن باگهایی که تستهای توخالی نمیبینند اسکن میکند: pip install brasscoders.




گفتگو