پرش به محتوای اصلی
پرش به محتوای مقاله

تست‌های خودکار جایگزین بازبینی دستی کد در پروژه‌های هوش مصنوعی شدند

·۸ مهر ۱۴۰۵۱۱ دقیقه مطالعه۲ بازدید
تحلیل
نمایی هنری از حماسه‌های مصنوعی: کهکشانی از داستان‌های تولیدشده توسط هوش مصنوعی در حال گسترش.
نمایی هنری از حماسه‌های مصنوعی: کهکشانی از داستان‌های تولیدشده توسط هوش مصنوعی در حال گسترش.
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

ارائه یک مدل عملیاتی برای حذف بازبینی دستی کد (Manual Code Review) و جایگزینی آن با ترکیبی از معماری تفکیک‌شده و تست‌های Fuzzing در یک پروژه واقعی.

تصور کنید کدی را در پروژه خود قرار می‌دهید که هرگز خط به خط آن را نخوانده‌اید، اما مطمئن هستید که کار می‌کند. این رویکرد جسورانه، مرز بین برنامه‌نویسی سنتی و عصر جدیدی است که در آن انسان از «نویسنده» به «ناظر» تبدیل می‌شود.

به گزارش وب‌سایت scattered-thoughts.net، یک توسعه‌دهنده مستقل توانسته است یک ویرایشگر متن را به‌طور کامل با استفاده از کدهای تولیدشده توسط هوش مصنوعی زاینده (Generative AI) بازسازی کند. او در ۲۸ سپتامبر ۲۰۲۶ اعلام کرد که نسخه جدید ویرایشگرش، هم قابلیت‌های بیشتری دارد و هم باگ‌های کمتری نسبت به نسخه اولیه که به‌صورت دستی نوشته شده بود، نشان می‌دهد. این دستاورد ثابت می‌کند که تست‌های خودکار و سخت‌گیرانه می‌توانند جایگزین بازبینی دستی کد شوند. این رویکرد یادآور سازوکارهای پیشرفته‌تری است که در سیستم AIDDSkeleton برای تبدیل دستورالعمل‌های متنی به کدهای اجرایی به کار گرفته شده تا صحت خروجی‌های AI تضمین شود.

این تحول در حالی رخ می‌دهد که صنعت نرم‌افزار با پدیده‌ای به نام Vibe Coding — یعنی تکیه بر «حس خوب» برنامه‌نویس به جای تایید رسمی کد — دست‌وپنجه نرم می‌کند. در حالی که بسیاری از توسعه‌دهندگان می‌ترسند که کدهای تولید شده توسط AI باعث ایجاد «بدهی فنی» (Technical Debt) نامرئی شوند، این پروژه راهکاری متفاوت پیشنهاد می‌دهد: مدل AI را به عنوان یک موتور اجرای سریع در نظر بگیرید و خودتان صرفاً بر معماری و مشخصات (Specification) تمرکز کنید.

معماری اعتماد

برای جلوگیری از اثر «غول چراغ جادو» — حالتی که مدل دستورات را به‌صورت تحت‌اللفظی اجرا می‌کند اما منطق کلی و بدیهیات را نادیده می‌گیرد — توسعه‌دهنده یک تفکیک معماری سخت‌گیرانه ایجاد کرد. پروژه به دو بخش (Crate) در زبان Rust تقسیم شده است:

  • focus-core: شامل منطق اصلی است. این بخش رویدادهای ورودی را می‌گیرد و دستورات رندر (کاراکترها و مستطیل‌ها) را برمی‌گرداند. برای ارتباط با دنیای خارج، از یک trait قابل شبیه‌سازی به نام &mut dyn IO استفاده می‌کند. طبق معیارهای scc، این بخش شامل ۳۴ فایل با ۱۳٬۸۳۱ خط کد (۱۰۶۷ خط خالی، ۱٬۸۵۶ کامنت و ۱۰٬۹۰۸ خط کد واقعی) و امتیاز پیچیدگی ۱٬۲۰۲ است.
  • focus: مسئول پیاده‌سازی واقعی trait مربوط به IO، رابط خط فرمان (CLI) و منطق Daemonization است. این بخش کوچک‌تر است و ۸ فایل با ۳٬۶۶۱ خط کد (۲۸۸ خط خالی، ۷۲۰ کامنت و ۲٬۶۵۳ خط کد واقعی) و پیچیدگی ۲۵۷ دارد.

این جداسازی اجازه می‌دهد تست‌های سرتاسری (End-to-End) برای منطق هسته بدون نیاز به محیط واقعی اجرا شوند. توسعه‌دهنده اشاره می‌کند که مدل‌های AI، به‌ویژه Claude 3.5 Opus — که از طریق Claude Code و با اشتراک ۲۰ دلاری استفاده شده — تمایل شدیدی به نوشتن تست‌های واحد (Unit Tests) دارند. با ایجاد یک رابط عمومی پایدار، او مانع از آن شد که AI مرزهای داخلی کد را به‌هم بریزد یا در آن‌ها «سوراخ» ایجاد کند.

مدیریت رابط کاربری با AI

تعامل با مدل نیازمند تغییر در استراتژی پرامپت‌نویسی بود. او دریافت که دستورات مستقیم مثل «X را انجام بده» باعث می‌شود AI بدون گزارش خطاهای احتمالی، با خشونت از موانع عبور کند و کد را تحویل دهد. به همین دلیل، اکنون از عبارت «می‌خواهم X را انجام دهم. سوالی داری؟» استفاده می‌کند تا خطاها و ابهامات پیش از شروع پیاده‌سازی شناسایی شوند. این استراتژی برای کاهش خطاهای نوشتاری، مشابه برخی از رویکردهای Sanity و Notion در مهار خطاهای عامل‌های AI است که بر بازبینی و تایید متقابل تاکید دارند.

اگرچه مدل‌ها در رعایت دستورات تست و شناسایی لبه‌های خاص (Edge Cases) که حتی از چشم انسان دور مانده بود، پیشرفت کرده‌اند، اما هنوز گاهی شکست می‌خورند. در یک مورد، مدل Opus به‌درستی در برابر یک دستور اشتباه مقاومت کرد و هشدار داد که اجرای تحت‌اللفظی آن باعث بروز یک مشکل بدیهی می‌شود، هرچند چنین پیش‌بینی‌هایی هنوز نادر هستند. توسعه‌دهنده اشاره می‌کند که در برخی جنبه‌ها هنوز مدل Pi را ترجیح می‌دهد، هرچند بیشتر زمان خود را به جای تعامل با محیط مدل، صرف کار با فایل‌های متنی می‌کند.

پذیرش تست‌های «شل و ول» (Slop Testing)

به جای بررسی وسواس‌گونه هر خط کد Rust تولید شده توسط AI، توسعه‌دهنده به متدی تکیه کرده که آن را «Slop» می‌نامد؛ تست‌هایی که نوشتنشان خسته‌کننده است و پوشش (Coverage) کمی دارند، اما در شناسایی پس‌روی‌ها (Regressions) بسیار موثرند.

ابزار اصلی او یک Fuzzer است که برنامه را باز کرده، هزاران کلید تصادفی را ارسال می‌کند و سپس تابع app.assert_invariants() را فراخوانی می‌کند. با وجود اینکه توسعه‌دهنده اعتراف می‌کند این روش پوشش ضعیفی دارد، اما باعث شده ویرایشگر برای چندین هفته استفاده فعال، بدون هیچ کرشی (Crash-free) کار کند. برای پروژه‌ای که تنها یک کاربر دارد و ریسک از دست دادن داده‌های حیاتی در آن نیست، تکیه بر این «Slop» و رفع باگ‌ها تنها در زمان مواجهه واقعی، بسیار بهینه‌تر از بازبینی دستی است.

نمونه‌های تست سرتاسری

برای اطمینان از عدم تخریب قابلیت‌های اصلی، تست‌های E2E تعامل کاربر را شبیه‌سازی می‌کنند. برای مثال، تست انتخاب پوشه (dir_picker_ctrl_enter_descends_into_selected_dir) مراحل زیر را طی می‌کند:

  • ایجاد یک برنامه موقت (Scratch app) و درج یک فایل فرضی در مسیر /proj/src/main.rs.
  • شبیه‌سازی فشردن کلید Ctrl+M و یک تیک زمانی (Tick).
  • شبیه‌سازی Ctrl+Enter برای ورود به پوشه /proj/.
  • تایید اینکه ویرایشگر مسیر را اکنون /proj/ نشان می‌دهد و لیست شامل src/ می‌باشد.
  • فراخوانی app.assert_invariants() برای اطمینان از عدم فساد وضعیت داخلی.

این نوع اتوماسیون در تست‌های سرتاسری، با تلاش عامل‌های Playwright برای ترمیم خودکار چرخه تست نرم‌افزار هم‌سو است که هدف هر دو، کاهش دخالت دستی در اعتبارسنجی است.

عملکرد و تست‌های مجانبی

برای جلوگیری از افت سرعت، تست‌های مجانبی (Asymptotic Tests) پیاده شدند. این موضوع حیاتی است زیرا حتی جدیدترین مدل‌ها مکرراً کدهایی با پیچیدگی زمانی درجه دو (Quadratic) می‌نویسند که می‌تواند یک برنامه در محیط عملیاتی را کاملاً منجمد کند.

تست‌هایی مانند rust_highlighting_is_linear از یک تابع بررسی استفاده می‌کنند که:

  • یک فایل نمونه را در دو اندازه متفاوت (SMALL و LARGE) باز می‌کند.
  • زمان لازم برای هر دو عملیات را اندازه می‌گیرد.
  • نرخ رشد و مقدار MB/s را محاسبه می‌کند.
  • تایید می‌کند که رشد در محدوده MAX_GROWTH و سرعت بالای MIN_MB_PER_SECOND است.

مدل عملکردی فعلی این است: «با باز بودن حداکثر ۱۶ پنجره و فایل‌های زیر ۲۰۰ کیلوبایت، هیچ ورودی نباید بیش از ۱۶ میلی‌ثانیه زمان پردازش و رندر روی این لپ‌تاپ بگیرد».

مقابله با زوال AI

برای جلوگیری از تبدیل شدن پروژه به یک آشفتگی ناشی از Vibe Coding، توسعه‌دهنده از تست‌های Snapshot برای رابط‌های عمومی و داخلی استفاده می‌کند. با بررسی تغییرات این اسنپ‌شات‌ها به جای بررسی کد خام، او می‌تواند «انتزاع‌های نشت‌کننده» (Leaky Abstractions) — جایی که جزئیات داخلی به‌اشتباه وارد API عمومی می‌شوند — را سریعاً شناسایی کند.

برای مثال، اسنپ‌شات رابط عمومی برای focus_core::buffer به‌طور صریح ساختار BufferId و پیاده‌سازی Buffers شامل متدهایی مانند keys() و from_file() را ردیابی می‌کند.

safeguard دیگر، یک «تست خنده» (Cackle Test) است که کد را برای شناسایی فراخوانی‌های تصادفی توابع IO از درون منطق هسته اسکن می‌کند. این کار تضمین می‌کند که AI مرزهای شبیه‌سازی را دور نمی‌زند. توسعه‌دهنده مجبور است برخی موارد مانند Seed کردن Hashmap از /dev/random را در لیست سفید قرار دهد و برخی crateهایی که اسکریپت‌های build آن‌ها با تست تداخل دارد را غیرفعال کند.

مرزهای شبیه‌سازی و محدودیت‌ها

با وجود موفقیت، توسعه‌دهنده این راهکار را «ارزان و بی‌کیفیت» می‌نامد. محدودیت‌های جدی در Rust وجود دارد:

  • نبود Mockهای استاندارد: هیچ راه معقولی در Rust برای تزریق Mock برای کتابخانه استاندارد (Stdlib) وجود ندارد.
  • شکاف Sans-IO: اکثر کتابخانه‌ها به سبک sans-io نوشته نشده‌اند، به این معنی که نمی‌توانند از trait شبیه‌سازی‌شده IO استفاده کنند.
  • منطق غیرقابل تست: بخش بزرگی از فراخوانی‌های کتابخانه‌ای باید خارج از focus-core قرار گیرند و تست آن‌ها دشوار است؛ برای مثال منطق Daemonization بسیار سخت تست می‌شود و مکرراً دچار پس‌روی (Regression) می‌شود.

او برای حل این مشکل، استفاده از WASI یا یک هایپروایزر را برای ایجاد محیطی شبیه به «Antithesis-lite» بررسی می‌کند تا تمام فراخوانی‌های خارجی را به داخل مرز شبیه‌سازی بیاورد، هرچند این مورد هنوز در نقشه راه فوری نیست.

طراحی داده‌محور برای پایداری AI

برای جلوگیری از سردرگمی AI در مسائل پیچیده مالکیت (Ownership) و طول‌عمر (Lifetime) در Rust، او از معماری طراحی داده‌محور (Data-Oriented Design) استفاده کرد. در این روش، به جای گراف‌های پیچیده از اشیاء، همه چیز در مجموعه‌های جداگانه ذخیره می‌شود که با Handleها ایندکس شده‌اند.

در ساختار Buffers داده‌ها به نقشه‌های متعددی تقسیم شده‌اند:

  • source: Map<BufferId, Source>
  • text: Map<BufferId, BString>
  • highlight: Map<BufferId, Highlight>
  • newlines: Map<BufferId, Vec<usize>>
  • last_modified_time: Map<BufferId, Duration>
  • undos: Map<BufferId, Vec<Vec<Vec<Edit>>>>
  • doing: Map<BufferId, Vec<Vec<Edit>>>
  • redos: Map<BufferId, Vec<Vec<Vec<Edit>>>>
  • last_center_offset: Map<BufferId, usize>

این رویکرد مانع از آن می‌شود که AI در «سوراخ‌های خرگوش» خطاهای Borrow-checker بیفتد، زیرا Rust به‌راحتی تشخیص می‌دهد که buffers.text و buffers.source تداخلی با هم ندارند.

گردش‌کار انسان-AI

توسعه‌دهنده رویکردهای «عامل‌محور» (Agentic) شامل چندین عامل موازی و چندین Git worktree را «آشفتگی خسته‌کننده» خوانده و رد کرده است. در عوض، او از یک روش تک‌رشته‌ای استفاده می‌کند:

۱. نوشتن یک طراحی دقیق برای یک دسته از کارها.
۲. برگزاری جلسه پرسش‌و‌پاسخ هم‌زمان با مدل برای رفع ابهامات.
۳. اجازه دادن به AI برای پیاده‌سازی در حالی که انسان به فعالیت‌های فیزیکی (مثل پیاده‌روی یا مطالعه یک مقاله) می‌پردازد.
۴. بازبینی و تست نتایج در بازه‌های کوتاه ۱۵ دقیقه‌ای.

این ریتم باعث شد قابلیت‌های پیچیده‌ای مثل یکپارچگی با VCS پیاده شوند که در نسخه دستی هرگز تکمیل نشده بودند. توسعه‌دهنده حتی به تغییر در ریتم شخصی خود اشاره می‌کند؛ او کمتر به موسیقی الکترونیک با BPM بالا گوش می‌دهد و بیشتر به سراغ Grime و Acid Rock رفته است که بازتاب‌دهنده سبکی از کار است که کمتر متمرکز و بیشتر توزیع شده است.

تغییر در ارزش برنامه‌نویسی

این تجربه نشان می‌دهد که مرز «کیفیت در برابر تلاش» جابه‌جا شده است. اگرچه ممکن است با هجوم نرم‌افزارهای متوسط تولیدشده توسط AI مواجه شویم، اما جایگزین آن اغلب «نداشتن نرم‌افزار» است.

برای یک فرد، هزینه داشتن یک «برنامه‌نویس شخصی» به ۲۰ دلار در ماه کاهش یافته است. گلوگاه دیگر توانایی نوشتن کد نیست، بلکه توانایی تعریف دقیق رفتار (Specification) و ساخت سیستم‌هایی است که بتوانند آن رفتار را تایید کنند. او این وضعیت را به کالاهای کارخانه‌ای تشبیه می‌کند؛ کارهای دست‌ساز «روح» دارند، اما کاربرد آسفالت، گوشی و دوچرخه‌های تولید انبوه غیرقابل انکار است.

چشم‌انداز آینده

این پروژه نشان می‌دهد آینده مهندسی نرم‌افزار در توسعه «شبیه‌سازی-محور» است. با ساخت دنیایی که کدهای AI بتوانند Fuzz شوند و به‌صورت رسمی بررسی شوند، توسعه‌دهندگان می‌توانند بدون فدا کردن پایداری، سریع‌تر حرکت کنند. او به‌ویژه علاقه‌مند است بداند چگونه می‌توان از طریق Capabilities/Effects، متدهای رسمی، Model Checking و Sandboxing اعتماد ایجاد کرد یا آسیب‌ها را کاهش داد.

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

گام بعدی شما

  • اگر از AI برای کدنویسی استفاده می‌کنید، به جای بازبینی خط به خط، روی نوشتن تست‌های Fuzzing و Invariant-check تمرکز کنید.
  • معماری پروژه خود را به بخش‌های «منطق خالص» و «رابط‌های خارجی» تقسیم کنید تا شبیه‌سازی تست‌ها ساده‌تر شود.
  • از مدل‌ها بخواهید پیش از پیاده‌سازی، سوالات خود را درباره طراحی شما بپرسند تا از خطاهای منطقی جلوگیری شود.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

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

تأثیر برای ایران

برای برنامه‌نویسان ایرانی که به دلیل محدودیت‌های سخت‌افزاری یا بودجه‌ای به ابزارهای ارزان‌تر تکیه می‌کنند، این متدولوژی امکان تولید نرم‌افزارهای پیچیده را با هزینه کم (اشتراک ۲۰ دلاری) و ریسک پایین فراهم می‌کند.

·نگاه ما
تحریریه دات‌هوش

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

منابع

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

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.