یک پرامپت که هر کدبیسی را به یک سند تست دستی کامل و تعاملی تبدیل میکند.
فایلهای سورس را میدهی، یک فایل HTML مستقل تحویل میگیری — صدها تست قابلقضاوت به صورت عمل و انتظار، ثبت وضعیت، پیشرفت زنده، جستجو، فیلتر و ذخیرهسازی. بدون build، بدون وابستگی.
پیش از اجرای این دستورات، مقادیر مشخصشده را تکمیل کنید. هر عبارتی که میان [~ و ~] قرار دارد، یک جاینگهدار (placeholder) است که باید جایگزین شود؛ سایر بخشها دستورالعملهای ثابت هستند.
صفحات با کمک هوش مصنوعی تولید شده است.
سندهای تست دستی معمولاً به سه دلیل قابلپیشبینی میپوسند:
| مشکل | در عمل چه شکلی است |
|---|---|
| انتظارِ مبهم | «لاگین درست کار میکند.» دو تستر دو برداشت متفاوت میکنند و هیچکدام نمیتواند باگ دقیقی ثبت کند. |
| رفتار ساختگی | سند از اندپوینت یا پیام یا فلگی حرف میزند که اصلاً در کد نیست. تستر دنبال چیزی میگردد که وجود ندارد. |
| اجرای بدون ردگیری | دویست ردیف در یک اسپردشیت؛ کسی نمیداند کدامها واقعاً اجرا شدهاند و با بستن تب همهچیز از بین میرود. |
این پرامپت هر سه را از پایه حل میکند:
- هر انتظار باید قابلقضاوت باشد — یک عدد، یک رشتهٔ دقیق، تعداد ریکوئست، یا وجود و نبودِ یک کلید استوریج. عبارتی مثل
works correctlyصراحتاً ممنوع است. - هیچچیز نباید ساخته شود — نامها و روتها و پیامها و ثابتها مستقیماً از کد واقعی برداشته میشوند. ابهامِ واقعی بهجای حدسزدن، به تستی با عنوان
undefined behavior — needs a decisionتبدیل میشود. - پیشرفت ذخیره میشود — وضعیت هر ردیف در
localStorageزیر یک کلید نسخهدار مینشیند، همراه شمارندههای زنده و پیشرفت جداگانهٔ هر بخش.
ℹ️ نکته
ارزشمندترین تستها همانهایی هستند که پرامپت عمداً شکارشان میکند: گاردها، فالبکها، و تمایزهایی که نویسندهٔ کد بین حالتهای خطا قائل شده است. وقتی «آفلاین» و «رمز اشتباه» به یک پیام واحد فرو میریزند، هیچ کرشی رخ نمیدهد و هیچ تستی فیل نمیشود — محصول فقط بیسروصدا بدتر میشود. این پرامپت دقیقاً همین دسته از باگها را میگیرد.
یک فایل. با دابلکلیک باز میشود. آفلاین کار میکند.
your-project/
├── src/
└── scenarios.html ← the entire deliverable
|
ردگیری
|
پیمایش
|
|
ساختار
|
جزئیات
|
۱. پرامپت را کپی کن داخل ایجنتت — هر ابزاری که بتواند فایل بخواند و یک فایل بنویسد.
۲. پروفایل بالای پرامپت را پر کن. هر جاینگهدارِ داخل علامتهای راهنما جایگزین میشود؛ بقیهٔ متن دقیقاً همانطور که هست باقی میماند.
- Target paths (files or folders to read): [~…~]
+ Target paths (files or folders to read): src/auth/, src/api/client.js, appsettings.json
- Backend stack: [~…~]
+ Backend stack: ASP.NET Core 8 (C#), EF Core, JWT auth
- Document language: [~…~]
+ Document language: Persian
- Text direction: [~…~]
+ Text direction: RTL
- Numeral style in rendered output: [~…~]
+ Numeral style in rendered output: Eastern Arabic (۰-۹)
- Output file name: [~…~]
+ Output file name: scenarios.html۳. اجرا کن. ایجنت کد را میخواند و بعد فایل خروجی را کنار همان کد مینویسد.
۴. فایل خروجی را باز کن و تست را شروع کن. پیشرفت خودش ذخیره میشود.
💡 توصیه
مسیرهای هدف را به فایلهایی بده که منطق جالب در آنهاست: احراز هویت، کلاینت HTTP، اعتبارسنجی، مدیریت خطا. دادنِ کل مونوریپو سند را عمیقتر نمیکند، سطحیترش میکند.
بخش ۰ — پروفایل پروژه
تابلوی کنترل. همهچیز از اینجا خوانده میشود و همین است که پرامپت را مستقل از استک میکند.
| فیلد | چرا مهم است |
|---|---|
Target paths |
تنها فایلهایی که ایجنت اجازهٔ خواندنشان را دارد. یک گاردریل هم هست، چون نباید جای دیگری سرک بکشد. |
Project type |
تعیین میکند سند به تست مرورگری نیاز دارد یا تست ترمینالی یا هر دو. |
Backend / Frontend stack |
ابزار درست را انتخاب میکند. مثلاً دستور ریست دیتابیس، مکانیزم ذخیرهسازی سمت کلاینت، و اینکه کلاینت HTTP کدام باشد. |
Other moving parts |
صفها و کرانجابها و وبهوکها. هرکدام یک بخش اضافه میکند، چون باگهای زمانبندی و تلاش مجدد همانجا زندگی میکنند. |
Document language / direction |
بومیسازی کامل، شامل چیدمان راستبهچپ. |
Body font / Code font |
فونت متن در برابر فونت کد و شناسهها. کد ویژگیهای direction:ltr و unicode-bidi:isolate میگیرد تا داخل متن فارسی بههم نریزد. |
Numeral style |
ارقام لاتین یا ارقام فارسی. |
Theme / Output format |
تم تیره یا روشن، و خروجی HTML یا Markdown. |
بخش ۱ — اول کد را بخوان
قاعدهای که خروجی را قابلاعتماد میکند. چهار محدودیت دارد:
- کامل بخوان، حدس نزن.
- نامهای واقعی را بردار: توابع، کلاسهای CSS، کلیدهای استوریج، روتها، رشتههای خطا، و ثابتهایی مثل تایماوت و طول عمر توکن و حداقل طول.
- هرگز نساز. نه API، نه تابع، نه پیام. ابهام به یک تست با عنوان «رفتار تعریفنشده، نیازمند تصمیم» تبدیل میشود، نه به داستان.
- منطق عامدانه را پیدا کن: گاردها، فالبکها، و تمایزهایی که نویسنده بین حالتهای خطا گذاشته است.
⚠️ مهمقاعدهٔ سوم همان چیزی است که سند مفید را از سند خوشظاهر جدا میکند. یک پیام خطای ساختگی، یک ساعت از وقت تستر را میگیرد و اعتمادش به تمام ردیفهای دیگر را نابود میکند.
بخش ۲ — محتوای تست
ساختار سند
- بخش صفر، آمادهسازی محیط. تنظیماتی که قبل از تست باید عوض شوند، هرکدام با سه چیز: مقدار عادی، مقدار پیشنهادی برای تست، و دلیلش. کوتاهکردن طول عمر توکن از پانزده دقیقه به دو دقیقه، یک تست انقضای غیرقابلاجرا را قابلاجرا میکند. بهعلاوه ابزارهای لازم و کلیدهای استوریج و متغیرهای محیطی و دستور ریست کامل.
- بخشهای اصلی. یکی برای هر ماژول یا صفحه یا فلو، شمارهدار، با زیربخشهای شمارهدار.
- بخش سرتاسری. فلوهای کامل از ابتدا تا انتها.
- دو جدول خلاصه که پایینتر توضیح داده شدهاند.
قواعد هر ردیف
| قاعده | در عمل |
|---|---|
| دقیقاً دو ستون | ستون اقدام و ستون انتظار. در جدولهای اعتبارسنجی، ستون اول میتواند ورودی باشد. |
| انتظار قابلقضاوت | یک عدد، یک پیام دقیق، تعداد ریکوئست، یا یک کلید استوریج. عبارت مبهم مجاز نیست. |
| شناسهٔ پایدار | مثل 3.8.1، تا گزارش باگ بتواند به آن ارجاع بدهد. |
| رویدادِ رخندادنی، صریح | بنویس «هیچ ریکوئستی ارسال نمیشود» یا «توکنها پاک نمیشوند» یا «صفحه ریلود نمیشود». |
| منطق طراحی | هرجا رفتار درست بهنظر غلط میآید، تا کسی باگ اشتباه ثبت نکند. |
| یادداشت قرمز امنیتی | هرجا رفتارِ بهظاهر بیخطر در واقع یک آسیبپذیری است. |
چکلیست پوشش: مرزهای اعتبارسنجی شامل خالی و فقطفاصله و یکیکمتر و یکیبیشتر و پیست و کاراکتر غیرمجاز · آفلاین و سرور خاموش · انقضای زمانی · دابلکلیک سریع · پاسخ ناقص یا خراب · حملهٔ XSS و ورودی غیرلاتین · همزمانی چند تب و ریکوئستهای در جریان · دسترسپذیری با کیبورد · چیدمان ریسپانسیو · و احترام به کاهش انیمیشن.
دو جدول خلاصه همان بخشی است که بقیه از سندشان کپی میکنند:
| جدول | قاعده |
|---|---|
| 🔴 خطا حتماً باید ظاهر شود | نبودنِ خطا، خودش باگ است. |
| 🟢 هیچ خطایی نباید ظاهر شود | هر خطا یا بنر یا خروج از حسابی اینجا، باگ است. |
جدول دوم همان چیزی است که کسی خودش نمینویسد، و دقیقاً جایی است که رگرسیونهای بیصدا گیر میافتند. خارجشدن از حساب هنگام یک قطعی لحظهای شبکه، هیچ تستی را نمیشکند و هیچ اکسپشنی پرتاب نمیکند. فقط به کاربر یاد میدهد هر بار که وایفای تپق زد، رمزش را دوباره تایپ کند.
بخش ۳ — تحویلدادنی
یک فایل مستقل، نوشتهشده کنار کد. بدون build، بدون نصب، بدون فایل جانبی.
- حالت HTML: باید با دابلکلیک باز شود، و کل سند باید از یک مدل دادهٔ واحد جاوااسکریپت در انتهای فایل رندر شود. هدف این است که اضافهکردن یک تست، فقط اضافهکردن یک ردیف آرایه باشد.
- حالت Markdown: فقط جدول و تیتر ساده، شناسه در سلول اول، و یک ستون چکباکس بهجای کنترلهای تعاملی.
- هیچچیز حذف نشود. اگر سند مبدأیی دادهای، هر جدول و یادداشت و بلوک کد در آن باید منتقل شود.
بخش ۴ — امکانات تعاملی، فقط در حالت HTML
سه دکمه برای هر ردیف · کلیک برای پاککردن وضعیت · رنگگرفتن کل ردیف · ذخیرهسازی زیر یک کلید نسخهدار · نوار پیشرفت چسبان با شمارندههای زنده · نوار کوچک و شمارندهٔ انجامشده از کل برای هر بخش · جستجوی زنده · چهار فیلتر وضعیت · بخشهای تاشو · دکمهٔ باز و بستن همه · فهرست کناری با هایلایت اسکرول · بازگشت به بالا · ریست همه با تأیید.
نسخهداربودنِ کلید استوریج مهم است: با بالابردن نسخه، همهٔ تسترها از صفر شروع میکنند بهجای اینکه نتیجههایی را به ارث ببرند که به ردیفهای دیگری اشاره میکردند.
بخش ۵ — طراحی
- فونت متن برای نثر، و فونت کد فقط برای کد و شناسهها.
- کد ویژگیهای
direction:ltrوunicode-bidi:isolateمیگیرد. در سند راستبهچپ این غیرقابلمذاکره است، وگرنه یک مسیر سادهٔ لاتین وسط جملهٔ فارسی وارونه رندر میشود. - پالت رنگ از متغیرهای CSS خود پروژه برداشته میشود تا سند شبیه محصول باشد. اگر متغیری وجود نداشت، یک پالت حرفهای و آرام متناسب با تم انتخابی.
- خوانایی مقدم بر تزئین: ارتفاع خط سخاوتمندانه، سلسلهمراتب روشن، ردیفهای کارتمانند، و بوردر نرم.
- رنگ یادداشتها معنادار است: 🔵 اطلاع · 🟡 هشدار · 🔴 خطر و امنیت.
- ریسپانسیو تا ۳۶۰ پیکسل، یعنی ستونها روی هم میروند و هدرهای چسبان چسبندگیشان را رها میکنند. استایل چاپ هم همهچیز را باز میکند و کنترلها و سایدبار را مخفی.
بخش ۶ — قواعد نهایی
| قاعده | چرا |
|---|---|
رندر با textContent یا escape درست |
سندی که دربارهٔ XSS حرف میزند، خودش نباید تزریقپذیر باشد. |
نوشتن \x3Cscript داخل رشتههای JS |
یک تگ بستهٔ واقعی داخل رشته، بلوک اسکریپت را میبندد و فایل را خراب میکند. |
| گزارش تعداد کل تستها و بخشها | اولین بررسی سلامتِ پوشش. |
| ساختهشدن فقط همان یک فایل | بدون مارکداون اضافی و بدون خروجی جانبی. |
| استفاده فقط از مسیرهای دادهشده | ایجنت بدون اجازه نباید جای دیگری را بگردد. |
تفاوت بین ردیفی که تستر میتواند رویش اقدام کند و ردیفی که ردش میکند:
- Action: Test the login form
- Expectation: Should work correctly+ ID: 1.1.2
+ Action: Email of three spaces " ", then click Sign in
+ Expectation: Inline message `Email is required.` under the field; the field gets
+ class `.field--error`; no request is sent (Network tab stays empty).سه چیز عوض شد. اقدام قابل بازتولید است، یعنی ورودی دقیق و کلیک دقیق. انتظار، رشتهٔ دقیق و کلاس CSS دقیق را نام میبرد. و رویدادِ رخندادنی صریح است، یعنی «هیچ ریکوئستی ارسال نمیشود» خودش ادعای اصلی است و در تب Network قابل راستیآزمایی.
حالا دو نوع یادداشت، که پرامپت آنجا نانش را درمیآورد:
ℹ️ منطق طراحی — ردیف
1.2.4رمزی که فقط فاصله است، همانطور که تایپ شده ارسال میشود و trim نمیشود. حذف فاصلههای رمز یعنی تغییر بیصدای اعتبارنامهای که کاربر شاید عمداً انتخابش کرده. فقط ایمیل trim میشود.
بدون این یادداشت، یک تسترِ دقیق موضوع را بهعنوان باگ ثبت میکند و یک نفر یک بعدازظهر رویش وقت میگذارد.
🔒 امنیت — ردیف
1.2.7پیام رمز اشتباه و پیام حساب ناموجود باید بایتبهبایت یکسان باشند. هر تفاوتی در متن، یک آسیبپذیری شمارش کاربر است.
این به نظر یک ایراد نگارشی میآید. در واقع یک بردار برداشت حساب کاربری است.
هر چیزی در خروجی HTML از یک آرایه رندر میشود. اضافهکردن تست یعنی اضافهکردن یک آبجکت:
{
id: '2.4.3',
a: 'Trigger three expired requests at once (open three items quickly)',
e: 'Exactly <b>one</b> <code>POST /api/auth/refresh</code>, not three; ' +
'all three item requests then succeed.',
note: {
k: 'info', // 'info' | 'warn' | 'sec'
t: 'Design rationale: the refresh call is de-duplicated behind a single ' +
'in-flight promise. More than one refresh in the Network tab is the bug.'
}
}کلید id شناسهٔ پایدار است، a ستون اقدام، e ستون انتظار، و note همان یادداشت رنگی با سه نوع اطلاع و هشدار و امنیت.
ردیفها داخل گروه، و گروهها داخل بخش قرار میگیرند:
const SECTIONS = [
{ id: '2', title: 'Authentication, JWT lifetime and session', groups: [
{ id: '2.4', title: 'Access-token expiry and silent refresh',
cols: ['Action', 'Expectation'],
rows: [ /* … */ ] }
]},
// kind:'plain' → reference table, no pass/fail buttons
{ id: '9', title: 'Summary — An error MUST appear', kind: 'plain', groups: [ /* … */ ] }
];فرار از کاراکترهای خطرناک بهصورت متمرکز انجام میشود: هر رشته اول کامل escape میشود و بعد فقط یک لیست ثابت از تگهای درونخطی دوباره فعال میگردد. نوشتن محتوا راحت میماند و سند تزریقناپذیر.
اجرای مرجع در این ریپو روی یک برنامهٔ تکصفحهای به نام catalog-service انجام شده، با بکاند ASP.NET Core 8 و EF Core و JWT، و فرانتاند جاوااسکریپت خالص. نتیجه ۱۱۳ تست قابلبررسی در ۱۱ بخش است:
| شماره | بخش | تعداد |
|---|---|---|
0 | آمادهسازی محیط | ۲۲ ردیف مرجع |
1 | فرم لاگین و اعتبارسنجی ورودی | ۱۸ تست |
2 | احراز هویت و طول عمر توکن و نشست | ۲۵ تست |
3 | لیست کاتالوگ و جستجو و صفحهبندی | ۱۴ تست |
4 | فرم ساخت و ویرایش آیتم | ۱۹ تست |
5 | آفلاین و سرور خاموش و پاسخ خراب | ۱۰ تست |
6 | همزمانی و دابلکلیک و چند تب | ۸ تست |
7 | دسترسپذیری و کیبورد و چیدمان | ۱۰ تست |
8 | فلوهای سرتاسری، شامل دو مورد نیازمند تصمیم | ۹ تست |
9 | خلاصه، خطا حتماً باید ظاهر شود | ۱۹ ردیف |
10 | خلاصه، هیچ خطایی نباید ظاهر شود | ۲۱ ردیف |
چند ردیف نمونه از خود سند:
| شناسه | اقدام | انتظار |
|---|---|---|
1.1.6 |
پیستکردن یک ایمیل با حروف بزرگ و فاصلههای اضافی در دو طرف | پذیرفته میشود و بدنهٔ ریکوئست نسخهٔ trim و کوچکشدهٔ آن را حمل میکند. ℹ️ فیلد ورودی حروف بزرگ کاربر را نگه میدارد و فقط payload نرمالسازی میشود. |
2.4.1 |
بیکار ماندن تا بعد از طول عمر توکن، سپس کلیک روی یک آیتم | اول پاسخ 401، بعد دقیقاً یک درخواست refresh با پاسخ 200، و در آخر تلاش مجدد ریکوئست اصلی با 200. کاربر به صفحهٔ لاگین فرستاده نمیشود و هیچ خطایی نمیبیند. |
5.1.1 |
آفلاینکردن شبکه از ابزار توسعهدهنده، سپس ارسال فرم لاگین | پیام مخصوص آفلاین نمایش داده میشود و توکنها پاک نمیشوند. |
6.2.3 |
گذاشتن توکن تا انقضا، سپس اقدام همزمان در دو تب | هر تب حداکثر یک بار refresh میکند و توکن حاصل در هر دو تب معتبر است. |
8.3.1 |
رفتار تعریفنشده، نیازمند تصمیم: یک پیشنویس ذخیرهشده وجود دارد و کاربر دیگری وارد میشود | در کد مشخص نشده. باید تصمیم گرفت: یا پیشنویس هنگام ورود پاک شود، یا بهازای شناسهٔ هر کاربر جدا نگه داشته شود. تا وقتی تصمیم گرفته نشده، هیچکدام را باگ ثبت نکن. |
اول ساعتها را کوتاه کن. توکن پانزدهدقیقهای در عمل تست انقضا را غیرقابلاجرا میکند، چون کسی پایش نمینشیند و ردیف بدون اجرا قبول میخورد. دو دقیقه واقعیاش میکند. همین برای طول عمر توکن تازهسازی و پنجرهٔ محدودیت نرخ هم صدق میکند. دقیقاً به همین دلیل بخش صفر برای هر تنظیم، هر سه مورد مقدار عادی و مقدار تست و دلیل را میخواهد.
اختلاف مجاز ساعت را صفر کن. مقدار پیشفرض پنجدقیقهای، توکنهای خیلی بعد از انقضا را هم میپذیرد، پس یک تست انقضای درست، مردود بهنظر میرسد. قبل از هر تست زمانمحور صفرش کن، وگرنه دنبال باگی میگردی که وجود ندارد.
تمام مدت ابزار توسعهدهنده را روی تب شبکه نگه دار. حدود یکسوم انتظارها تعداد ریکوئستاند. «دقیقاً یک تازهسازی، نه سهتا» از روی رابط کاربری اصلاً دیده نمیشود، چون صفحه در هر دو حالت یکسان است.
به یادداشتهای قرمز اعتماد کن. ردیفهای امنیتی جاییاند که محصول سالم بهنظر میرسد و نیست. پاسخ موفق در ردیف 2.3.4، یعنی بازپخش توکن بعد از خروج از حساب، یعنی خروج اصلاً کسی را خارج نمیکند.
با تغییر ردیفها، نسخهٔ استوریج را بالا ببر. شمارهگذاری مجدد تستها درحالیکه تسترها نتایج قدیمی را نگه داشتهاند، بیصدا نتیجهٔ دیروز را به ردیف امروز میچسباند.
ردیفهای رقابتی را چند بار اجرا کن. ردیفهای 3.2.6 و 6.2.3 ذاتاً متناوباند. یک بار قبولشدن چیز زیادی ثابت نمیکند، سه بار میکند.
بدون دادن کد هم کار میکند؟
بله، اما نتیجه را با دقت بخوان. بدون مسیر هدف، یک سند خوشساخت تولید میکند که با مقادیر نمونهٔ محتمل برای استکِ اعلامشده پر شده؛ روتها و پیامها و کلیدهایی که واقعی بهنظر میرسند ولی با هیچ کدی تطبیق داده نشدهاند. بهعنوان اسکلت یا دمو مفید است، اما قبل از اجرای واقعی باید هر ثابت را با کد اصلی جایگزین کنی. خروجی مرجع همین ریپو دقیقاً به همین شکل تولید شده و خودش هم این را از ابتدا اعلام میکند.
از چه استکهایی پشتیبانی میکند؟
هر استکی. فیلدهای استک در بخش صفر تمام تصمیمهای ابزاری را هدایت میکنند: دستور ریست، مکانیزم ذخیرهسازی، کلاینت HTTP، و حتی اینکه اصلاً تست مرورگری موضوعیت دارد یا نه. هیچ نظری دربارهٔ فریمورک تو ندارد؛ دقیق توصیفش کن، ابزار خودش دنبالش میآید.
چرا یک فایل، بهجای یک ابزار مدیریت تست درستوحسابی؟
چون دوام میآورد. یک فایل HTML روی هر ماشینی باز میشود، به اکانت و سرور و نصب نیاز ندارد، کنار کدی که تستش میکند کامیت میشود، و در ریویو قابل مقایسه است. وقتی سند تست داخل یک سرویس ابری زندگی میکند، ظرف یکی دو ریلیز از کد فاصله میگیرد.
جایگزین تست خودکار است؟
نه، مکمل آن است. هدفش چیزهایی است که اتوماسیون بد یا گران پوشش میدهد: انقضا با ساعت واقعی، رفتار آفلاین، رقابت چند تب، چیدمان در عرض ۳۶۰ پیکسل، ترتیب فوکوس کیبورد، احترام به کاهش انیمیشن، و اینکه آیا پیام خطا چیز درستی به یک انسان میگوید یا نه. ضمناً چند ردیف عملاً بهعنوان مشخصات تستهایی کار میکنند که باید خودکارشان کنی.
میشود خروجی Markdown گرفت؟
کافی است قالب خروجی را روی Markdown بگذاری. جدول و تیتر ساده میگیری، شناسه در سلول اول، و ستون چکباکس بهجای کنترلهای تعاملی. در عوض ذخیرهسازی و جستجو و فیلتر و پیشرفت زنده را از دست میدهی. این معاملهٔ چیزی است که مستقیم روی گیتهاب رندر میشود.
بعداً چطور خروجی را گسترش بدهم؟
فایل را باز کن، تا آرایهٔ بخشها در انتها اسکرول کن، و یک آبجکت اضافه کن. این محدودیت عمدی است: کل سند از همان آرایه تولید میشود، پس یک تست جدید همیشه یک ردیف است، نه ویرایش مارکآپ.
تحت لایسنس MIT. با خیال راحت استفاده کن.
به دردت خورد؟ ⭐ به ریپو بده.
QA مبتنی بر پرامپت · مستقل از استک · بدون وابستگی