نشانهٔ شکست اتوماسیون همیشه قرمزشدن Pipeline نیست. گاهی Dashboard سبز است، اما تیم برای هر انتشار تستها را دوباره دستی اجرا میکند؛ گاهی ۳۰۰ Test دارید، ولی هیچکس نمیداند Fail امروز باگ محصول است یا مشکل داده؛ و گاهی Retry سوم سبز میشود و یک Race واقعی برای ماهها «Flaky» نام میگیرد.
اشتباهات اتوماسیون تست معمولاً از یک Locator بد یا ابزار اشتباه بزرگترند. اتوماسیون یک سیستم اجتماعی-فنی است: سؤال و ریسک، مرز اجرا، داده و محیط، کد تست، Runner، Report، مالک و تصمیم انتشار باید با هم کار کنند. اگر یکی از این حلقهها مبهم باشد، اسکریپت بیشتر فقط ابهام را سریعتر تکرار میکند.
پاسخ کوتاه: Suite سالم باید دربارهٔ یک ریسک مشخص، در بودجهٔ معلوم، روی Build/Environment/Data قابلشناسایی، نتیجهای تکرارپذیر و قابلتوضیح بسازد. برای نجات Suite ابتدا نشانه را با داده ثابت کنید، Fail را به Product/Test/Data/Environment/Infrastructure/Unknown طبقهبندی کنید، نخستین نقطهٔ انحراف را پیدا کنید، مکانیزم را اصلاح کنید و با اجرای قبل/بعد اثر درمان را نشان دهید. خرید ابزار، Timeout بیشتر یا Retry عمومی قبل از این تشخیص، درمان نیست.
اتوماسیون تست چه زمانی واقعاً «موفق» است؟
موفقیت یعنی اتوماسیون برای یک تصمیم، شواهد قابلاتکا تولید کند. سرعت، پوشش، تعداد Test و نرخ Pass فقط وقتی ارزش دارند که این شواهد را بهتر کنند. قابلیت Test Automation در مدل Continuous Delivery مؤسسه DORA نیز به Suiteهای جامعِ ساخته و نگهداریشده نزدیک به توسعه اشاره میکند؛ اما وجود Suite بهتنهایی تحویل مداوم یا کیفیت را تضمین نمیکند. معماری، Version Control، CI، داده، Observability و همکاری هم لازماند.
قرارداد سلامت اتوماسیون
| فیلد | پرسش |
|---|---|
| Decision | این Test قرار است کدام تصمیم را پشتیبانی کند: Merge، Release، تشخیص یا پایش؟ |
| Risk/Question | کدام شکست یا سؤال مشخص هدف است؟ |
| Boundary | Unit، Component، Integration، Contract، API E2E یا UI؟ |
| Stimulus/Data | ورودی، State، Clock، Seed و پیششرط چیست؟ |
| Oracle | انتظار و اثر جانبی درست چگونه مستقل بررسی میشود؟ |
| Dependencies/Fidelity | Fake، Container، Sandbox یا سرویس واقعی و محدودیت هرکدام چیست؟ |
| Identity | Commit، Artifact، Environment، Config، Schema و Run ID کداماند؟ |
| Budget | مهلت بازخورد، Timeout و هزینهٔ منابع چقدر است؟ |
| Evidence | در Fail چه Log، Trace، Request ID، Expected/Actual و Artifactی داریم؟ |
| Owner/Recovery | چه کسی Triage میکند و در خرابی Test/Environment چه سیاستی داریم؟ |
اگر این فیلدها برای بخش مهمی از Suite پاسخ ندارند، مسئله پیش از Framework استراتژیک است. قالب انتخاب هدف، Pilot و Scale در راهنمای استراتژی اتوماسیون تست آمده است؛ این مقاله روی تشخیص و نجات Suite موجود تمرکز دارد.
هفت نشانهٔ هشدار در Suite خودکار
- توسعهدهنده برای فهم یک Fail بیش از اجرای Test زمان میگذارد.
- نتیجه با همان Commit و ورودی بین Pass و Fail جابهجا میشود.
- تیم بدون نگاه به علت، Job را Rerun میکند تا سبز شود.
- یک تغییر کوچک UI دهها Test نامرتبط را میشکند.
- Suite سبز است، اما Defectهای همان Failure mechanism به تولید میگریزند.
- زمان CI رشد میکند، ولی معلوم نیست کدام Test چه ریسکی را پوشش میدهد.
- Quarantine، Skip و Waiver بیشتر میشوند و مالک/تاریخ انقضا ندارند.
این نشانهها را با داده تأیید کنید. یک روز کند یا یک Fail زیرساختی، Suite را «شکستخورده» نمیکند؛ روند، مخرج و طبقهبندی لازم است.
چارچوب تشخیص: از Symptom تا Proof of Recovery
- Capture: نخستین Fail را با Evidence دستنخورده ذخیره کنید؛ قبل از Rerun.
- Identify: Commit/Artifact/Environment/Data/Config/Seed/Worker را قطعی کنید.
- Classify: Product، Test، Data، Environment، Infrastructure یا Unknown.
- Reproduce: همان ورودی و سپس Boundary کوچکتر را اجرا کنید.
- Locate: نخستین اختلاف Expected/Actual یا State transition را بیابید.
- Treat: مکانیزم خطا را اصلاح کنید؛ نه فقط Symptom را.
- Prove: نشان دهید Test پیش از Fix روی همان مکانیزم Fail و پس از آن Pass میشود.
- Prevent: Contract، Lint، Fixture، Guardrail، Ownership یا Monitor اضافه کنید.
طبقهبندی شکست
| کلاس | نمونه | رأی Pipeline |
|---|---|---|
| Product | محاسبهٔ مبلغ غلط یا Callback تکراری دو Ledger entry ساخته است. | Fail؛ مالک محصول تصمیم Severity/Release میگیرد. |
| Test | Locator به CSS موقتی چسبیده یا Oracle انتظار قدیمی دارد. | Fail تست؛ نباید Product defect گزارش شود. |
| Data | کاربر مشترک توسط Test موازی مصرف شده است. | Inconclusive/Data؛ Run قابل استناد نیست. |
| Environment | Migration اجرا نشده یا سرویس فقط Running است، نه Ready. | Inconclusive/Environment؛ Release evidence ناقص است. |
| Infrastructure | Runner دیسک پر، Registry قطع یا Browser crash کرده است. | Infra failure؛ Retry فقط طبق Policy محدود. |
| Unknown | Log/Trace/Identity کافی برای رأی نداریم. | Inconclusive، نه Pass و نه باگ قطعی. |
اشتباه ۱: شروع با ابزار، نه با تصمیم و ریسک
سؤال «Selenium یا Playwright؟» پیش از «چه شواهدی لازم داریم؟» ترتیب را وارونه میکند. ابزار Browser ممکن است برای خطر Serialization در API یا Idempotency دیتابیس مرز نامناسبی باشد.
درمان
- یک جمله بنویسید: «اگر X خراب شود، Test Y در مرز Z با Oracle Q باید آن را تشخیص دهد.»
- Candidateها را با Risk، تکرار، Manual toil، امکان کنترل/مشاهده، Fidelity، هزینهٔ نگهداری و ارزش تصمیم امتیازدهی کنید.
- روی یک Workflow کوچک Pilot بگیرید و معیار Stop/Scale داشته باشید.
- ابزار را با Capability matrix انتخاب کنید، نه شهرت، ترند یا مهارت یک نفر.
هیچ تستی صرفاً چون «تکراری» است نامزد خوبی نیست. اگر Oracle انسانیِ آن مبهم است، خودکارسازی ابهام را تثبیت میکند. ابتدا Example و Expected outcome را با صاحب دامنه روشن کنید.
اشتباه ۲: اتوماسیون چیزهای نامناسب
دو خطای متضاد رایجاند: خودکارکردن هر Test Case موجود، یا حذف هر کاری که به قضاوت انسانی نیاز دارد. اتوماسیون برای اجرای دقیق و تکرارپذیر عالی است؛ انسان برای کشف، تفسیر، یادگیری و ارزیابی تجربه نقش متفاوتی دارد.
| نوع کار | تصمیم محتمل |
|---|---|
| قاعدهٔ پایدار مالی با Oracle دقیق | Unit/Component خودکار |
| Contract API نسخهبندیشده | Contract/Integration خودکار |
| یک Journey حیاتی انتشار | API/UI E2E محدود و خودکار |
| Usability، فهم متن یا حس اعتماد | پژوهش/بررسی انسانی؛ اتوماسیون فقط Checkهای فنی مکمل |
| Feature آزمایشی با رفتار روزانه متغیر | اکتشاف و Instrumentation؛ خودکارسازی پس از تثبیت Contract |
| Case کمریسک و پرهزینه با اجرای نادر | دستی/on-demand یا حذف آگاهانه |
اشتباه ۳: قرار دادن تست در مرز اشتباه
«تست را تا جای ممکن پایین ببرید» اگر Failure mechanism را حذف کند غلط است. مرز درست، کوچکترین مرزی است که مکانیزم شکست، Fidelity و Oracle لازم را حفظ میکند. محاسبهٔ تخفیف در Unit، Serialization مبلغ در API، Constraint یکتایی در PostgreSQL و Journey پرداخت در System مرزهای متفاوتاند.
راهنمای هرم تست در عمل نسبتهای ثابت را رد میکند و انتخاب را بر Risk، Failure mechanism، Fidelity، Oracle و بودجهٔ بازخورد میگذارد. مقالهٔ Practical Test Pyramid نیز بر پرتفوی متوازن، پرهیز از Test duplication و کد تست تمیز تأکید دارد؛ Pyramid یک KPI شمارشی نیست.
اشتباه ۴: تمرکز افراطی روی UI
UI تنها جایی است که برخی ریسکها مثل Focus، Navigation، Browser integration و Journey واقعی دیده میشوند؛ اما تستکردن تمام قواعد از UI زمان، نقاط شکست و ابهام را زیاد میکند. یک Fail میتواند از DOM، Browser، Network، API، DB، داده یا محیط باشد.
درمان
- قاعدهٔ دامنه را در Unit/Component، Interface را در Contract/Integration و فقط رفتار منحصربهفرد کاربر را در UI نگه دارید.
- یک Case را در همهٔ لایهها کپی نکنید؛ هر Test سؤال و Failure mechanism متمایز داشته باشد.
- Journeyهای UI را محدود، مالکدار و با Budget زمانی صریح کنید.
- Setup را در صورت امنبودن از API انجام دهید، ولی Outcome کاربر را در مرز هدف بررسی کنید.
اشتباه ۵: Locator و انتظار شکننده
Selectorهایی مثل .css-18x:nth-child(3) به پیادهسازی موقت میچسبند. sleep(5000) هم نه آمادگی را ثابت میکند و نه عملکرد را؛ روی CI کند میشود و روی Local زمان هدر میدهد.
مستندات رسمی Best Practices پلیرایت رفتار قابلمشاهدهٔ کاربر، Isolation، Locatorهای مبتنی بر Role/Label/Text، Auto-wait و Web-first assertions را توصیه میکند. این قابلیتها Flakiness را کم میکنند، اما Contract مبهم، State مشترک یا Backend ناپایدار را حل نمیکنند.
قبل و بعد
// شکننده: DOM داخلی + انتظار ثابت + Oracle ضعیف
await page.locator('.btn.primary:nth-child(2)').click();
await page.waitForTimeout(5000);
expect(await page.locator('.toast').isVisible()).toBe(true);
// مقاومتر: قرارداد کاربر + انتظار روی نتیجهٔ معنادار
await page.getByRole('button', { name: 'پرداخت' }).click();
await expect(page.getByRole('heading', { name: 'پرداخت موفق' }))
.toBeVisible();
اگر Role/Name درست وجود ندارد، مشکل فقط Test نیست؛ Accessibility/Testability contract محصول نیاز به اصلاح دارد. data-testid برای جایی که قرارداد کاربر کافی نیست قابلقبول است، به شرط اینکه Stable و مالکدار باشد.
اشتباه ۶: State و دادهٔ مشترک
Test A سفارشی را میسازد و Test B همان را Refund میکند؛ روی اجرای ترتیبی سبز و در Parallel قرمز میشود. یا همهٔ Testها با یک کاربر/کد ملی/شماره موبایل کار میکنند و Rate limit یا موجودی یکدیگر را تغییر میدهند.
راهنمای رسمی Avoid sharing state در Selenium روی دادهٔ مستقل، پاکسازی دادهٔ stale و Driver تازه برای هر Test تأکید میکند. استقلال باید فقط Browser Context نباشد؛ رکورد DB، Queue، فایل، Cache، Feature flag و Dependency side effect هم باید Namespace داشته باشند.
قرارداد دادهٔ تست
- Run ID و Worker ID در همهٔ رکوردهای قابلجستوجو؛
- Factory/Builder با Seed و Scenario name؛
- مالکیت و TTL برای Cleanup؛
- Reset کوچک و Scopeدار، نه پاککردن DB مشترک؛
- عدم استفاده از دادهٔ Production بدون مجوز و کنترل حریم خصوصی؛
- ظرفیت و Rate limit برای Parallel run؛
- Oracle مستقل که رکورد «همین Run» را بررسی کند.
برای Synthetic data، Masking، Isolation، Retention و مثالهای هویتی/مالی ایران از راهنمای مدیریت داده تست استفاده کنید.
اشتباه ۷: نادیده گرفتن Testability محصول
Testی که نمیتواند Clock، Random، Dependency، Failure، State یا Identity را کنترل کند، با Sleep، Mock پنهان و Retry جبران میشود. همچنین اگر Outcome فقط در Log پراکنده یا Queue بدون Correlation قابلدیدن باشد، Oracle قابلاتکا ساخته نمیشود.
درمان معماری
- Clock/ID/Random/PSP/Queue را از طریق Seam صریح کنترل کنید.
- Run ID و Business correlation را از Request تا DB/Event منتقل کنید.
- Endpoint یا Fixture امن برای Setup/Reset محیط غیرتولید داشته باشید.
- Outcome و Side effect را بدون دسترسی خطرناک به internals قابلمشاهده کنید.
- Failure injection را مجاز، محدود، Audited و خارج از دسترس کاربر عادی طراحی کنید.
این موضوع فراتر از Framework تست است. راهنمای طراحی برای تستپذیری یک Testability Contract برای Control، Observe، Oracle، Reset، Reproduce و Diagnose ارائه میکند.
اشتباه ۸: محیط «بالاست» ولی آماده نیست
Process Running یا Port Open به معنای Ready بودن Schema، Migration، Cache warm-up یا Dependency نیست. Test زودتر شروع میشود، Fail میکند و تیم با Sleep یا Retry آن را پنهان میکند.
مستندات Startup و Wait Strategy در Testcontainers تفاوت Startup state و آمادگی قابلاستفاده برای Test را صریح میکند و Waitهای HTTP، Healthcheck، Log و Strategy سفارشی ارائه میدهد. Readiness باید به پیششرط واقعی Scenario وصل باشد؛ ۲۰۰ شدن یک endpoint عمومی شاید Migration پرداخت را ثابت نکند.
Environment Manifest
- Artifact digest و Commit؛
- Config hash و Feature flags؛
- Schema/Migration/Seed version؛
- Dependency endpoint/version/mode؛
- Locale، Timezone و Clock policy؛
- Runner/Browser/OS/CPU/RAM؛
- Readiness evidence و زمان ثبت؛
- Run ID و Cleanup status.
Drift، IaC، Readiness، دسترسی و ظرفیت محیط در راهنمای مدیریت محیط تست با جزئیات بیشتری پوشش داده شده است.
اشتباه ۹: Retry را درمان Flaky Test دانستن
Retry یک مشاهدهٔ دوم میسازد؛ علت را حذف نمیکند. اگر Fail اول و Pass دوم روی همان Commit رخ دهد، نتیجه «Flaky/retry-pass» است، نه Pass پاک. ممکن است Race محصول، Eventually consistent بدون Oracle، شبکه، دادهٔ مشترک یا Test defect باشد.
مستندات Retries در Playwright نیز نتیجهٔ Passed، Flaky و Failed را جدا میکند. از Retry محدود برای جمعآوری Evidence و جلوگیری از توقف ناشی از Infra شناختهشده استفاده کنید، اما Fail نخست را حفظ و Trend کنید.
سیاست Flaky و Quarantine
- Fail نخست، Trace و Artifact پیش از Retry ذخیره شود.
- Retry فقط برای کلاسهای مجاز و تعداد محدود باشد.
- retry-pass نتیجهٔ Flaky بگیرد و Owner/Issue بسازد.
- Quarantine باید Risk، Owner، تاریخ انقضا و پوشش جایگزین داشته باشد.
- Test پرریسک بدون پوشش جایگزین از Gate حذف نشود.
- رفع با ۲۰ یا تعداد توافقشده Run متوالی روی شرایط مرتبط اثبات شود؛ عدد را از نرخ پایه انتخاب کنید.
اشتباه ۱۰: POM و Abstraction افراطی
Page Object میتواند Locator و سرویس صفحه را متمرکز کند، اما یک God Object با متدهای چندمنظوره، Assertionهای پنهان و Sleepهای عمومی، تشخیص را سختتر میکند. DRY مطلق نیز Intent تست را پشت Helperهای تو در تو پنهان میکند.
مستندات رسمی Page Object Models در Selenium Page/Component object را Interface سرویسهای UI میداند، Locator را در یک مکان نگه میدارد و Assertion نتیجه را عموماً مسئول Test میگذارد. POM یک Pattern ممکن است، نه معماری اجباری هر Suite.
قواعد کد تست قابلتشخیص
- نام Test سناریو و Outcome را بیان کند.
- Arrange/Act/Assert یا Given/When/Then در خواندن قابلتشخیص باشد.
- Helper دامنهای باشد:
checkout.payByCard()، نهclickSecondBlueButton(). - Assertion اصلی و Expected/Actual نزدیک Intent بماند.
- Fixtureها State و Cleanup پنهان نسازند.
- Abstraction فقط وقتی استخراج شود که یک مفهوم پایدار و مالک روشن دارد.
اصول تغییرپذیری، Composition، Fixture و مرز POM در راهنمای کد تست قابل نگهداری آمده است.
اشتباه ۱۱: Oracle ضعیف و Pass کاذب
کلیک موفق یا HTTP ۲۰۰ نتیجهٔ کسبوکار را ثابت نمیکند. در پرداخت، ممکن است API موفق باشد اما Ledger ثبت نشده، Outbox دو پیام ساخته یا مبلغ ریال/تومان اشتباه باشد.
Oracle چندلایه
- Interface: Status، Schema و خطای دامنهای؛
- State: وضعیت سفارش/پرداخت؛
- Side effect: Ledger، Event، موجودی یا Notification؛
- Invariant: At-most-once، سقف Refund، جمع حسابداری؛
- User-visible: پیام، Focus، مسیر و امکان اقدام بعدی؛
- Negative: آنچه نباید رخ دهد، مثل درخواست PSP برای مبلغ صفر.
Oracle را از همان منطق Production کپی نکنید. Contract تاییدشده، حسابداری مستقل، مدل ساده، Metamorphic relation یا منبع مرجع کوچکتر میتواند استقلال بسازد.
اشتباه ۱۲: گزارش سبز/قرمز بدون Evidence
Screenshot آخرین صفحه برای سیستم توزیعشده کافی نیست. Fail باید قابل پاسخگویی باشد: چه چیزی انتظار میرفت، چه چیزی دیده شد و نخستین اختلاف کجا بود؟
Evidence Pack حداقلی
- Test ID، Risk ID و Owner؛
- Commit، Artifact digest، Environment/Config/Data identity؛
- Start/end، Duration، Worker، Attempt و Seed؛
- Expected/Actual با Diff کوچک؛
- Request/Order/Trace/Run correlation IDs؛
- Log، network، console، DB/Event observation و Timeline؛
- Screenshot/Video/Trace فقط در حد لازم و بدون PII/Secret؛
- Classification، Known issue، Quarantine/Waiver و Cleanup result.
برای UI، راهنمای Debugging و Trace Viewer پلیرایت DOM snapshot، Timeline، Network، Console و Source را کنار هم میگذارد. Trace میتواند دادهٔ شخصی و Token داشته باشد؛ Retention و دسترسی آن باید کنترل شود.
اشتباه ۱۳: CI فقط Test را اجرا میکند
Job سالم یک قرارداد دارد: Runtime/Lockfile، Test selection، Exit code، Timeout، Retry، Report، Artifact، Retention و Missing-report policy. آپلود JUnit بهخودیخود Gate نیست. مستندات Unit Test Reports در GitLab صریح میگوید JUnit XML وضعیت Job را تغییر نمیدهد؛ فرمان Test باید Exit code درست بدهد.
گیت درست
- Baseline و Preconditionهای Environment قبل از Test؛
- Fail شدن Job با Exit غیرصفر محصول/Test، نه با Pipeline سبز و Report قرمز؛
- همیشه-آپلودشدن Report/Log در Fail؛
- Missing یا Empty report بهعنوان خطا؛
- Retry فقط Infra و Idempotent؛
- Artifact tested once و Promotion همان Artifact؛
- Testهای Slow/Event-driven در Lane جدا؛
- Secret، Fork/MR و Runner trust boundary صریح.
نمونهٔ اجرایی امن، Cache/Artifact/JUnit و Troubleshooting در راهنمای GitLab CI برای تست خودکار قرار دارد.
اشتباه ۱۴: سنجش تعداد Test و درصد Pass بهعنوان ROI
تعداد زیاد میتواند Duplicate، Test کمارزش یا خردشدگی افراطی باشد. نرخ Pass نیز با حذف Testهای سخت یا Retry بیشتر قابلبازی است. ROI را با اثر بر تصمیم و هزینهٔ چرخه بسنجید.
سنجههای سالم
- Time to first reliable signal؛
- زمان Triage از Fail تا Classification؛
- درصد Failهای دارای Evidence کافی؛
- First-attempt pass/fail و retry-pass جدا؛
- Flaky/Quarantine count و سن آنها؛
- Change amplification: یک تغییر محصول چند Test را بیدلیل میشکند؟
- هزینهٔ Runner و Rerun برای هر Evidence قابلاقدام؛
- Risk evidence coverage با مخرج؛
- Defectهای گریخته به تفکیک Failure mechanism؛
- Maintenance load و زمان صرفشده برای Test/Environment/Data.
در راهنمای متریکهای تست میتوانید برای هر شاخص سؤال، مخرج، Owner، Freshness و تصمیم تعریف کنید. Score بدون اقدام، Dashboard تزئینی است.
ماتریس تشخیص سریع
| نشانه | شاهد لازم | علتهای محتمل | اقدام اول |
|---|---|---|---|
| فقط روی CI Fail | Runtime/OS/Browser/CPU/trace diff | Config drift، منابع، Headless، Timezone | Manifest Local و CI را مقایسه کنید. |
| تنها در Parallel Fail | Run/Worker/Data IDs | State مشترک، Port/File/User collision | Namespace و تصادفیسازی Order را بررسی کنید. |
| پس از Retry Pass | Attempt-1 evidence | Race محصول، Readiness، شبکه، Test | Flaky طبقهبندی؛ Fail نخست را Triage کنید. |
| Timeout مداوم | Step duration و dependency latency | Wait اشتباه، Backend کند، Deadlock | Earliest slow step را جدا کنید؛ Timeout عمومی را زیاد نکنید. |
| تغییر UI، شکست گسترده | Locator ownership map | Selector داخلی، God POM، Duplication | Locator contract و Component object را اصلاح کنید. |
| Suite سبز، باگ تولید | Risk→Test→Oracle trace | مرز/Fidelity/Oracle غلط یا Gap مدل | Incident را به Failure mechanism و missing evidence نگاشت کنید. |
| Testها اجرا نمیشوند | Discovery list و report count | Tag/rule/path misconfiguration | Non-empty/discovery guard اضافه کنید. |
| Environment Fail مبهم | Readiness/Migration/Dependency manifest | Running≠Ready، Drift، Capacity | Preflight و Readiness معنادار بسازید. |
نمونهٔ نجات: Checkout ایرانی
فرض کنید Suite Checkout شامل ۱۴۰ تست UI است، ۴۵ دقیقه زمان میبرد و ۱۲٪ Runها با Retry سبز میشوند. باگ «Callback موفق دیرهنگام پس از Timeout» به تولید گریخته است.
ممیزی Failure mechanism
| ریسک | مرز مناسب | داده/Dependency | Oracle |
|---|---|---|---|
| ریال/تومان و تخفیف مرزی | Unit/Component | IRR canonical + کلاسهای مرزی | مبلغ دقیق و invariant نامنفی |
| رقم فارسی/عربی در ورودی | Component/API | Unicode table | Normalize/Reject طبق Contract |
| Idempotency Callback | DB/Queue Integration | PSP virtual service + PostgreSQL | دقیقاً یک Ledger/Outbox effect |
| Timeout پس از Commit | Integration/System | Fault کنترلشدهٔ PSP | Reconciliation و عدم Debit دوم |
| Journey کاربر | UI E2E | یک Sandbox/Fake کالیبره | وضعیت قابلفهم و امکان پیگیری |
| UTC/Asia-Tehran | Unit + Integration | Clock تزریقشده | مرز انقضا/تسویه طبق Policy |
اقدام نجات
- ۱۱۰ Case قاعده/ترکیب را از UI به Unit/Component/API منتقل کنید؛ نه با کپی، با مالکیت سؤال.
- سه Journey منحصربهفرد UI نگه دارید: موفق، ردشده و نتیجهٔ نامشخص/پیگیری.
- PSP virtual service برای Timeout-before/after-commit، Duplicate و Signature invalid بسازید.
- Run ID را به Order، Payment attempt، Callback، Ledger و Outbox ببرید.
- دادهٔ هر Worker را Namespace و Cleanup را TTLدار کنید.
- Sleep را با State/Response readiness و Web-first assertion جایگزین کنید.
- Attempt اول، Trace، Network و Side-effect snapshot را ذخیره کنید.
- معیار موفقیت را ۴۵→۱۵ دقیقه فرضی نگذارید؛ Baseline بگیرید و هدف را بر Feedback budget توافق کنید.
این تغییر تعداد UI Test را کم میکند، اما هدف کاهش عدد نیست؛ هر ریسک در مرزی قرار میگیرد که Failure mechanism و Oracle آن را بهتر حفظ میکند.
انتخاب ابزار؛ ماتریس بهجای مسابقهٔ محبوبیت
| بُعد | پرسش Pilot |
|---|---|
| Interface | Web، Mobile، API، Desktop یا Protocol؟ |
| Runtime/Language | مهارت تیم، Debugger و Package governance چیست؟ |
| Isolation/Parallel | Context، Worker، Data و Shard چگونه جدا میشوند؟ |
| Synchronization | Auto-wait، Polling و Async events چه قراردادی دارند؟ |
| Evidence | Trace، Network، Console، Screenshot، Video، JUnit/JSON چقدر عملیاند؟ |
| Ecosystem | Browser/device، Plugin، Reporter و CI فعلی پشتیبانی میشود؟ |
| Security | Secret، Telemetry، Cloud dashboard و Artifact privacy چیست؟ |
| Iran operations | دانلود Browser/Driver/Package، Registry mirror و اجرای آفلاین ممکن است؟ |
| Migration | Test/Locator/Data/Report چقدر قابلانتقالاند؟ |
| Cost | License، Runner، نگهداری و آموزش طی ۱۲ ماه چیست؟ |
ابزار را روی دو سناریوی آسان و یک سناریوی سخت اجرا کنید؛ Demo ورود ساده محدودیت Trace، Parallel، SSO، فایل، چندتب یا Mobile Web را نشان نمیدهد.
آیا اتوماسیون دستی را جایگزین میکند؟
«دستی در برابر خودکار» تقسیمبندی ضعیفی است. اجرای ماشینی برای Regression دقیق، ترکیب داده و Gate مناسب است؛ انسان برای اکتشاف، مدلسازی ریسک، مشاهدهٔ الگوهای تازه، Usability و تفسیر Evidence ضروری است. یک تستر میتواند با ابزار اجرا کند و یک Developer میتواند Session اکتشافی انجام دهد؛ نقش را با مکانیزم کار تعریف کنید.
اتوماسیون بهخصوص نمیتواند از Specification مبهم، پاسخ درست بسازد. اگر Team دربارهٔ Outcome اختلاف دارد، ابتدا Example mapping، Review یا Session مشترک لازم است.
برنامهٔ ۳۰روزه برای نجات Suite
هفتهٔ اول: Inventory و Baseline
- برای هر Test: Risk، Boundary، Owner، Duration، Attempt، Flaky، Data/Environment و Last meaningful failure ثبت کنید.
- سه تا ده Run همسان برای Baseline بگیرید؛ مخرج را ثابت نگه دارید.
- Failهای اخیر را Product/Test/Data/Environment/Infra/Unknown طبقهبندی کنید.
هفتهٔ دوم: توقف خونریزی
- Evidence attempt اول، Non-empty guard و Missing-report failure را اضافه کنید.
- Shared account/data، hard wait و Locatorهای پرشکست را هدف بگیرید.
- Quarantineهای قدیمی را Owner/Expiry/coverage جایگزین بدهید یا برگردانید.
هفتهٔ سوم: جابهجایی مرز و Testability
- ۱۰ Test UI پرهزینه را با Failure mechanism مرور و به مرز مسئول منتقل/تقسیم کنید.
- Clock/Run ID/Reset/Dependency seamهای لازم را با توسعه بسازید.
- Readiness و Data namespace را در CI اعمال کنید.
هفتهٔ چهارم: Policy و Proof
- Laneهای Fast/Integration/E2E/Event-driven را با Budget و Gate جدا کنید.
- First-attempt، retry-pass، actionability، quarantine age و escaped mechanism را Dashboard کنید.
- Baseline قبل/بعد و دو Incident واقعی را با Evidence مقایسه کنید.
- برای Keep/Move/Split/Rewrite/Quarantine/Delete تصمیم مالکدار بگیرید.
چکلیست بازبینی هر Test خودکار
- یک Risk/Question و Outcome روشن دارد.
- در کوچکترین Boundary حافظ Failure mechanism است.
- داده، State، Clock و Dependency معلوم و کنترلپذیرند.
- Test مستقل از Order و Parallel قابلاجراست.
- Oracle نتیجه و Side effect معنادار را میسنجد.
- Fail محصول را از Test/Environment/Data قابلتفکیک میکند.
- Sleep و Retry عمومی ندارد؛ انتظار روی Condition واقعی است.
- Locator/Driver/API به Contract پایدار تکیه دارد.
- نام و ساختار، Intent را بدون دنبالکردن Helperهای زیاد نشان میدهد.
- Evidence شامل Identity، Expected/Actual و Correlation است.
- PII/Secret در Log، Screenshot، Video و Trace محافظت میشود.
- Owner، Lane، Budget و سیاست شکست دارد.
- Quarantine/Skip/Waiver محدود و تاریخدار است.
- ارزش تصمیم آن از هزینهٔ اجرا و نگهداری بیشتر است.
مستندات Unit Testing Best Practices مایکروسافت نیز Fast، Isolated، Repeatable و Self-checking بودن را ویژگیهای مهم Test واحد میداند. این اصول را نباید کورکورانه به E2E تعمیم داد، اما برای تشخیص علت کندی و وابستگی پنهان مفیدند.
پرسشهای متداول دربارهٔ اشتباهات اتوماسیون تست
از کجا بفهمیم مشکل Suite از ابزار است یا طراحی؟
یک سناریوی هدف را با Evidence کامل روی کوچکترین نمونه بازتولید کنید. اگر محدودیت بنیادی مانند Interface پشتیبانینشده، Report ناکافی یا ناسازگاری Runtime دارید، ابزار محتمل است. اگر همان Tool در نمونه پایدار ولی Suite اصلی با State مشترک، Oracle مبهم یا مرز غلط شکست میخورد، طراحی/محیط محتملتر است. Pilot مقایسهای از نظر حدس بهتر است.
نرخ Flaky قابلقبول چقدر است؟
عدد جهانی وجود ندارد. حتی نرخ کوچک در Testهای پرتکرار میتواند Rerun و بیاعتمادی زیادی بسازد. First-attempt failure و retry-pass را با مخرج Run، Lane، ریسک و Failure signature بسنجید؛ برای Testهای Gate حیاتی، تحمل باید بسیار کمتر از Checkهای تشخیصی باشد.
آیا Retry در CI بد است؟
Retry محدود و طبقهبندیشده برای Infra موقت یا جمعآوری Evidence مفید است؛ Retry عمومی که نتیجه را Pass پاک نشان دهد مضر است. Fail نخست باید حفظ شود، retry-pass باید Flaky بماند و Owner/Issue داشته باشد. Race محصول را با Retry به Test defect تبدیل نکنید.
برای کاهش هزینهٔ نگهداری، POM کافی است؟
خیر. POM فقط دانش UI و Locator را متمرکز میکند. مرز Test، State/Data isolation، Oracle، Testability، Evidence، CI و Ownership همچنان تعیینکنندهاند. POM بزرگ و چندمنظوره حتی میتواند Change amplification و Debug time را بیشتر کند.
کدام Testها را اول حذف یا بازنویسی کنیم؟
با Testهای پرهزینه، پرتکرار، بدون Owner/Risk، دارای Flaky/Quarantine قدیمی، Duplicate و فاقد Failure actionability شروع کنید. هرکدام را Keep، Move، Split، Rewrite، Quarantine موقت یا Delete کنید. Test حیاتی را فقط وقتی حذف کنید که Evidence جایگزین و Risk owner مشخص باشد.
جمعبندی
بیشتر پروژههای اتوماسیون با کمبود اسکریپت شکست نمیخورند؛ با شواهد غیرقابلاعتماد، مرز غلط، State مشترک، Oracle ضعیف، Environment بیهویت، Retry پنهانکننده و نبود مالک شکست میخورند. مسیر نجات چنین است: نشانه → Evidence → Identity → Classification → نخستین انحراف → درمان مکانیزم → Proof of recovery → Guardrail.
از Dashboard و ابزار شروع نکنید. یک Failure واقعی را بردارید، Health Contract آن را کامل کنید و هزینهٔ تشخیص را کم کنید. Suite موفق آن نیست که همیشه سبز باشد؛ آن است که وقتی رفتار مهمی عوض میشود، سریع و قابلتوضیح قرمز شود—و وقتی خودش خراب است، آن خرابی را صادقانه از نقص محصول جدا کند.

