Flaky टेस्ट

Flaky टेस्ट वह टेस्ट है जो प्रोडक्ट में कोई बदलाव हुए बिना उसी कोड पर कभी pass और कभी fail होता है। ऑटोमेशन suite के लिए यह सबसे नुक़सानदेह समस्या है: जब टीम यह मान लेती है कि लाल build “शायद flaky है”, तो वह suite पर भरोसा छोड़ देती है, और असली regressions शोर के साथ निकल जाते हैं।

यह गाइड UI और end-to-end टेस्ट में flakiness के आम कारण समझाती है, अंदाज़े के बजाय सबूत से flaky टेस्ट की जाँच कैसे करें, हर कारण को कैसे ठीक करें, और retries व quarantine को containment के रूप में कैसे इस्तेमाल करें ताकि वे समस्याएँ न छिपाएँ। यह UI टेस्ट ऑटोमेशन गाइड का हिस्सा है।

Flaky टेस्ट क्या है, और यह क्यों मायने रखता है

टेस्ट तब flaky है जब उसी commit और उसी environment configuration पर बार-बार चलाने से अलग-अलग नतीजे आएँ। दस बार चलाएँ तो शायद आठ pass और दो fail मिलें। नतीजा non-deterministic है, इसलिए अकेला कोई भी नतीजा प्रोडक्ट के बारे में ज़्यादा नहीं बताता।

इसकी लागत इसकी आवृत्ति से कहीं ज़्यादा है। हर flaky failure किसी की जाँच या rerun लेता है; कुछ बार ऐसा होने के बाद टीम हर failure को शोर मानने लगती है। Martin Fowler का non-determinism पर लेख सीधे कहता है: जो suite बेतरतीब ढंग से fail होता है वह signal के रूप में अपना मूल्य खो देता है। और flaky टेस्ट हमेशा ख़राब टेस्ट नहीं होता — कभी-कभी race condition प्रोडक्ट में ही होती है, और टेस्ट अकेला है जिसने उसे पकड़ा।

  • वही टेस्ट एक रन में fail और rerun में pass होता है, बीच में कोड में कोई बदलाव नहीं।
  • यह सिर्फ़ CI में, सिर्फ़ parallel में, दिन के कुछ ख़ास समय पर, या सिर्फ़ एक ब्राउज़र में fail होता है।
  • Failure message रनों के बीच बदलता है — एक में timeout, अगले में “element not found”।

Flaky UI टेस्ट के आम कारण

  • Timing और asynchrony — पेज तैयार होने से पहले action या assertion: अभी disabled बटन पर क्लिक, API response आने से पहले text पढ़ना, या ऐसा fixed sleep जो कभी-कभी छोटा पड़ जाता है।
  • Shared state और टेस्ट का क्रम — ऐसे टेस्ट जो किसी दूसरे टेस्ट के बनाए या बदले डेटा या browser state पर निर्भर हैं। एक क्रम में pass, दूसरे में fail, या अकेले चलाने पर fail।
  • टेस्ट डेटा की टक्कर — parallel टेस्ट जो एक ही account, एक ही email या एक ही product stock इस्तेमाल करते हैं; uniqueness constraints जो तब fail होते हैं जब दो रन एक ही “random” value चुन लेते हैं।
  • Environment — ओवरलोडेड CI runner, रन के बीच redeploy होता shared staging environment, धीमा container start-up, या runner पर अलग screen size, locale या time zone।
  • Third-party और remote services — payment sandboxes, SMS gateways, map tiles, feature-flag services और CDNs जो धीमे, अनुपलब्ध या rate-limited हों।
  • Animations और transitions — किसी एलिमेंट के खिसककर अपनी जगह आते समय उस पर क्लिक, या कुछ सेकंड में ग़ायब होने वाले toast message पर assertion।
  • समय और तारीख़ें — आधी रात, महीने के अंत और daylight-saving बदलावों के आसपास टूटने वाले टेस्ट, या जब runner का time zone ऐप के time zone से अलग हो।
  • बिना क्रम का डेटा — उस list की पहली row पर assertion जिसे server किसी तय क्रम में नहीं लौटाता।
  • Resource leaks — ब्राउज़र, sessions या database connections बंद न होना, जिससे लंबे रन में बाद के टेस्ट धीमे या fail होते हैं।
  • प्रोडक्ट के असली defects — race conditions, double submissions, invalidate न होने वाले caches। ये रिपोर्ट करने लायक bugs हैं, quarantine करने लायक test noise नहीं।

लक्षण और root causes: worked examples

यह टेबल आम flaky लक्षणों को, जैसे वे defect tracker में दिखते हैं, जाँच में मिले root cause और उसे हटाने वाले fix के साथ जोड़ती है। ध्यान दें कि कोई भी fix “लंबा sleep जोड़ें” या “retries चालू करें” नहीं है।

  • checkout.spec: “Place order” क्लिक लगभग 10 में से 1 रन में अनदेखा → कारण: कीमत दोबारा गिनने के बाद ही बटन enabled होता है → fix: enabled state assert करें और auto-wait पर भरोसा करें।
  • orders.spec सिर्फ़ refunds.spec के बाद चलने पर fail → कारण: refunds.spec साझा order cancel कर देता है → fix: हर टेस्ट API से अपना order ख़ुद बनाए।
  • signup.spec: parallel CI रनों में “email already registered” → कारण: दो workers एक ही email generate करते हैं → fix: generated डेटा में run/worker id और UUID जोड़ें।
  • report.spec रियाद समय के अनुसार 00:00 से 03:00 के बीच fail → कारण: runner UTC इस्तेमाल करता है, इसलिए “आज” की तारीख़ अलग है → fix: clock कंट्रोल करें या तारीख़ें एक ही time zone में निकालें।
  • profile.spec: “Saved” toast सिर्फ़ CI में नहीं मिलता → कारण: धीमे assertion से पहले toast ग़ायब हो जाता है → fix: अस्थायी toast के बजाय saved state assert करें।
  • map.spec parallel load में time out → कारण: third-party map tile service रन को rate-limit करती है → fix: map responses stub करें और एक contract check रखें।
For example (fictional):

Symptom (as a bug title)                                         Root cause                                  Fix
checkout.spec: "Place order" click ignored in ~1 of 10 runs      Button enabled only after price recalculated  Assert the enabled state; rely on auto-wait
orders.spec fails only when run after refunds.spec               refunds.spec cancels the shared order         Each test creates its own order via the API
signup.spec: "email already registered" in parallel CI runs      Two workers generate the same email           Add run/worker id + UUID to generated data
report.spec fails between 00:00 and 03:00 Riyadh time            Runner uses UTC, so "today" differs           Control the clock or compute dates in one zone
profile.spec: "Saved" toast not found on CI only                 Toast disappears before the slow assertion    Assert the saved state, not the transient toast
map.spec times out under parallel load                           Third-party tile service rate-limits the run  Stub map responses; keep one contract check

Flaky टेस्ट की जाँच

Flaky टेस्ट को किसी भी intermittent bug की तरह लें: उसे reproduce करें, fail हुए रनों से सबूत इकट्ठा करें, और एक बार में एक variable बदलें जब तक failure rate न हिले।

  • दोहराकर reproduce करें — एक टेस्ट को कई बार चलाएँ (Playwright में --repeat-each है; दूसरे runners में उनका repeat option या shell loop)। Failure rate “कभी-कभी fail होता है” को एक संख्या में बदल देता है जिसे fix से पहले और बाद में तुलना कर सकें।
  • एक condition बदलें — अकेले बनाम पूरे suite में, serial बनाम parallel, अलग क्रम, local बनाम CI, throttled CPU या network, दूसरा ब्राउज़र। जो condition failure rate बदलती है वही कारण की ओर इशारा करती है।
  • Fail हुए रन का सबूत पढ़ें — failure पर screenshot, video और trace। Playwright का trace viewer हर action को DOM snapshots, network requests और console messages के साथ दिखाता है; Cypress रनों के screenshots और videos ले सकता है; Selenium में अपने runner के failure hook में screenshot, browser logs और page source कैप्चर करें।
  • Back end से मिलाएँ — टेस्ट के बनाए request ids और timestamps log करें और server logs में वही समय-खिड़की देखें। Time zones का ध्यान रखें: CI runners अक्सर UTC इस्तेमाल करते हैं जबकि ऐप local time में log करता है।
  • History देखें — test reports और CI dashboards दिखाते हैं कि टेस्ट कब से flaky हुआ; उस तारीख़ की तुलना commits, dependency upgrades और environment बदलावों से करें।
// playwright.config.ts — keep evidence from failing runs
export default defineConfig({
  retries: process.env.CI ? 1 : 0,
  use: {
    trace: "on-first-retry",
    screenshot: "only-on-failure",
    video: "retain-on-failure",
  },
});

# reproduce locally: run one spec 50 times with 4 workers
npx playwright test tests/checkout.spec.ts --repeat-each=50 --workers=4

# open the trace from a failed CI run
npx playwright show-trace trace.zip

आम कारणों को ठीक करना

  • Timing — sleeps को condition-आधारित waits से बदलें: Selenium में explicit waits, Playwright में auto-waiting actions और web-first assertions, Cypress में .should() के साथ retry होने वाली queries। ऐप के अपने signal — कोई response या state बदलाव — का इंतज़ार करें, समय का नहीं।
  • Shared state — हर टेस्ट अपना डेटा और browser state ख़ुद बनाए, नए browser context से शुरू करे, और कभी इस पर निर्भर न रहे कि कोई दूसरा टेस्ट पहले चला।
  • डेटा की टक्कर — हर टेस्ट और हर worker के लिए unique values generate करें; parallel रनों से fixed “test user 1” जैसे accounts हटाएँ।
  • Environment — browser और dependency versions pin करें, suite को dedicated environment दें या रन के दौरान deployments रोकें, और workers की संख्या के हिसाब से CI runners का आकार रखें।
  • Third-party services — ज़्यादातर UI टेस्ट में उन्हें stub करें (Playwright में page.route, Cypress में cy.intercept, या mock server) और असली sandbox के ख़िलाफ़ एक छोटी, अलग रिपोर्ट होने वाली जाँच रखें।
  • Animations — किसी अस्थायी state के बजाय अंतिम state assert करें; जहाँ ऐप reduced-motion preference मानता है, टेस्ट में उसे emulate करें ताकि transitions छोटे हों या हट जाएँ।
  • समय — clock को कंट्रोल करें (Playwright की clock API, Cypress में cy.clock) या अपेक्षित तारीख़ें ऐप के time zone में निकालें।
  • क्रम — assert करने से पहले साफ़ तौर पर sort या filter करें; कभी न मानें कि पहली row वही है जो आपके टेस्ट ने बनाई।
// Flaky: guesses how long the save takes, then reads the text once
await page.getByRole("button", { name: "Save" }).click();
await page.waitForTimeout(2000);
expect(await page.getByTestId("status").textContent()).toBe("Saved");

// Stable: waits for the app’s own signal and retries the assertion
const saved = page.waitForResponse(
  (r) => r.url().includes("/api/profile") && r.request().method() === "PUT");
await page.getByRole("button", { name: "Save" }).click();
expect((await saved).ok()).toBeTruthy();
await expect(page.getByTestId("status")).toHaveText("Saved");

आज़माएँ: फ़ेक यूज़र जनरेटर आज़माएँ: टेस्ट डेटा फ़ैक्टरी आज़माएँ: Mock API रिस्पॉन्स जनरेटर आज़माएँ: API रिक्वेस्ट बिल्डर

Retries और quarantine: containment, इलाज नहीं

Automatic retries — Playwright की retries setting, Cypress का retries option, और TestNG व Maven Surefire जैसे runners के rerun features — flaky टेस्ट के बाद वाली कोशिश में pass होने पर pipeline को हरा कर देते हैं। Short-term containment के रूप में यह ठीक है और नीति के रूप में नुक़सानदेह: retries असली intermittent defects छिपाते हैं, pipeline धीमी करते हैं, और flaky rate को चुपचाप बढ़ने देते हैं। इस्तेमाल करें तो उन्हें दिखाई देने वाला बनाएँ; उदाहरण के लिए Playwright ऐसे टेस्ट को जो fail होकर retry में pass हुआ, “passed” नहीं बल्कि “flaky” रिपोर्ट करता है।

Quarantine दूसरा containment टूल है: किसी जाने-पहचाने flaky टेस्ट को merge रोकने वाले suite से निकालकर एक अलग, non-blocking job में रखें, जहाँ वह merges रोके बिना चलता और रिपोर्ट करता रहे। Fowler quarantine को main suite को भरोसेमंद रखने का तरीक़ा बताते हैं — इस चेतावनी के साथ कि quarantined टेस्ट जल्दी ठीक होने चाहिए, वरना वे किसी चीज़ की रक्षा नहीं करते।

  • CI में ज़्यादा से ज़्यादा एक retry और local में कोई नहीं, और “retry में pass” को flaky के रूप में रिपोर्ट करें।
  • पहले जाँचें कि failure प्रोडक्ट bug तो नहीं; असली defect को कभी quarantine न करें।
  • हर quarantined टेस्ट को owner, ticket और due date दें, और सूची की हर हफ़्ते review करें।
  • Quarantine में due date पार होने पर टेस्ट ठीक करें, निचले लेवल पर दोबारा लिखें, या हटा दें। हमेशा skip रहने वाला टेस्ट dead code है जो coverage जैसा दिखता है।
  • Quarantine की सीमा तय करें। अगर यह बढ़ती रहे, तो इसमें जोड़ना बंद करें और साझा कारण ठीक करें — आमतौर पर environment या test data रणनीति।
  • नीचे की उदाहरण नीति ठोस संख्याएँ जोड़ती है, जिन्हें अपनी टीम के हिसाब से बदला जा सकता है: जो टेस्ट उसी commit पर fail और pass दोनों हो, CI उसे flaky flag करता है; 1 working day में triage (प्रोडक्ट bug, टेस्ट bug या environment?); quarantine की due date ज़्यादा से ज़्यादा 10 working days; quarantine से बाहर तब, जब टेस्ट ठीक होकर --repeat-each के साथ लगातार 50 बार pass हो, या दोबारा लिखा या हटा दिया जाए; और हर हफ़्ते flaky सूची व हर suite के flaky-rate trend की review।
Flaky test policy (example)
- Detection:  a test that fails and passes on the same commit is flagged flaky by CI
- Retries:    at most 1 in CI, 0 locally; "passed on retry" is reported as flaky, not passed
- Triage:     within 1 working day: product bug, test bug or environment?
- Quarantine: non-blocking job, with ticket + owner + due date (max 10 working days)
- Exit:       fixed and 50 consecutive passes with --repeat-each, or rewritten / deleted
- Review:     weekly flaky list in the QA sync; flaky-rate trend per suite
Retries और quarantine सिर्फ़ containment हैं: retry में pass होना flaky गिना जाता है, प्रोडक्ट bug कभी quarantine में नहीं जाता, और quarantine जाँचे गए fix, दोबारा लिखने या हटाने पर ख़त्म होती है।
ट्रांज़िशन
#सेतकघटना या शर्त
1Merge रोकने वाला suiteशुरुआतFlaky flag हुआउसी commit पर fail और pass, या retry में pass: CI इसे passed नहीं, flaky रिपोर्ट करता है
2Flaky flag हुआTriage1 working day में: प्रोडक्ट bug, टेस्ट bug या environment?
3Triageप्रोडक्ट bug की तरह संभालाअंतप्रोडक्ट bug: असली defect कभी quarantine नहीं होता
4TriageQuarantinedटेस्ट bug या environment: owner, ticket और due date के साथ non-blocking job में
5Quarantinedठीक हुआ: जाँच जारीठीक किया गया
6ठीक हुआ: जाँच जारीMerge रोकने वाला suiteशुरुआत--repeat-each के साथ लगातार 50 pass: merge रोकने वाले suite में वापस
7Quarantinedनिचले लेवल पर दोबारा लिखाअंतनिचले लेवल पर दोबारा लिखें
8Quarantinedहटाया गयाअंतहटा दें

उदाहरण नीति; संख्याएँ बदली जा सकती हैं। Due date (अधिकतम 10 working days) पार हो तो ठीक करें, दोबारा लिखें या हटाएँ: हमेशा skip रहने वाला टेस्ट coverage जैसा दिखता dead code है। हर हफ़्ते review करें; बढ़ती quarantine यानी साझा कारण ठीक करें।

Ownership और माप

जिन flaky टेस्ट का कोई owner नहीं, वे flaky ही रहते हैं। Ownership प्रोडक्ट क्षेत्र के हिसाब से दें — जो टीम checkout की मालिक है वही checkout टेस्ट की — किसी एक “automation person” को नहीं, और flaky-test triage को side project के बजाय सामान्य definition of done का हिस्सा बनाएँ।

कुछ सरल माप दिखाते हैं कि हालात सुधर रहे हैं या नहीं। इन्हें हर suite के लिए ट्रैक करें और एक हफ़्ते के बजाय trend देखें।

  • Flaky rate — टेस्ट रनों का वह हिस्सा जो fail होकर retry में pass हुआ, या कोड बदलाव के बिना fail हुआ।
  • Top offenders — वे चंद टेस्ट जो ज़्यादातर flaky failures के ज़िम्मेदार हैं; इन्हें ठीक करने से आमतौर पर सबसे बड़ा सुधार मिलता है।
  • Time to fix — कोई टेस्ट कितने समय तक flagged या quarantined रहता है।
  • Rerun cost — retries और manual reruns पर ख़र्च हुए pipeline minutes और person-hours।

टेस्ट लिखते समय flakiness रोकना

  • कोई fixed sleep नहीं; हर wait timeout वाली एक condition है।
  • यूज़र को दिखने वाले नतीजों पर retry करने वाले assertions, एक बार पढ़ने वाले नहीं।
  • Role, label, text या test ids पर आधारित मज़बूत locators — locator रणनीतियों वाली गाइड देखें।
  • हर टेस्ट अपना डेटा बनाता है और उसका मालिक है, हर रन और हर worker के लिए unique values के साथ।
  • State API से set up होती है, असंबंधित screens पर क्लिक करके नहीं।
  • Third-party services stub की जाती हैं; जहाँ तारीख़ें मायने रखती हैं वहाँ clock और time zone कंट्रोल होते हैं।
  • नए टेस्ट blocking suite में जुड़ने से पहले कई बार चलाए जाते हैं — उदाहरण के लिए 20 से 50 बार।
  • Suite parallel में चलता है और समय-समय पर random order में, ताकि छिपी निर्भरताएँ जल्दी सामने आएँ।

अक्सर पूछे जाने वाले सवाल

Flaky टेस्ट क्या है?

Flaky टेस्ट ऐसा ऑटोमेटेड टेस्ट है जो प्रोडक्ट में कोई बदलाव हुए बिना उसी कोड और configuration पर अलग-अलग नतीजे — pass या fail — देता है। इसके अकेले नतीजे पर भरोसा नहीं किया जा सकता, जिससे पूरा suite कम उपयोगी हो जाता है।

क्या बस automatic retries चालू कर दें?

सिर्फ़ अस्थायी containment के रूप में, कम सीमा के साथ, और “retry में pass” को flaky रिपोर्ट करते हुए। अकेले retries असली intermittent bugs छिपाते हैं और flakiness बढ़ने देते हैं; हर flaky टेस्ट को फिर भी जाँच और fix चाहिए।

Test quarantine क्या है?

Quarantine किसी जाने-पहचाने flaky टेस्ट को merge रोकने वाले suite से निकालकर एक अलग, non-blocking रन में ले जाता है। टेस्ट ठीक होने तक यह main suite को भरोसेमंद रखता है, और तभी काम करता है जब हर quarantined टेस्ट का owner और deadline हो।

Flaky टेस्ट का कारण कैसे खोजें?

उसे कई बार चलाकर reproduce करें, फिर एक बार में एक condition बदलें — isolation, parallelism, क्रम, environment, ब्राउज़र — और failure rate देखें। Fail हुए रनों के screenshots, videos, traces और server logs को सबूत के रूप में इस्तेमाल करें।

क्या flaky टेस्ट हमेशा टेस्ट की ही समस्या है?

नहीं। कुछ flaky टेस्ट प्रोडक्ट में असली race conditions, double submissions या caching bugs उजागर करते हैं। टेस्ट को दोष देने से पहले इसे ख़ारिज करें, और अगर गड़बड़ प्रोडक्ट में है तो defect रिपोर्ट करें।

Flaky UI टेस्ट का सबसे आम कारण क्या है?

व्यवहार में timing की समस्याएँ सबसे आम कारणों में हैं: ऐप तैयार होने से पहले टेस्ट action या assertion कर देता है। Condition-आधारित waits, auto-waiting actions और retry करने वाले assertions इनमें से ज़्यादातर हटा देते हैं; इसके बाद shared data और अस्थिर environments आते हैं।

नए flaky टेस्ट को suite में आने से कैसे रोकें?

नए टेस्ट में sleeps, नाज़ुक locators और shared data की review करें, और हर नए टेस्ट को blocking suite में जोड़ने से पहले CI जैसी परिस्थितियों में कई बार चलाएँ। हर suite का flaky rate ट्रैक करने से जल्दी पता चलता है कि किसी बदलाव ने हालात बिगाड़े।

संदर्भ

  • Eradicating Non-Determinism in Tests (Martin Fowler)martinfowler.com · 2011flaky टेस्ट सूट का मूल्य क्यों नष्ट करते हैं, उनके आम कारण (isolation, asynchrony, remote services, समय, resource leak) और जवाब के रूप में quarantine।
  • Trace viewer — PlaywrightMicrosoft (Playwright)टेस्ट रन को क़दम-दर-क़दम रिकॉर्ड और रीप्ले करना — DOM स्नैपशॉट, नेटवर्क, कंसोल — ख़ासकर CI की विफलताओं का निदान करने के लिए।
  • Auto-waiting — PlaywrightMicrosoft (Playwright)हर एक्शन से पहले Playwright की actionability जाँचें — visible, stable, enabled, events प्राप्त करने योग्य — जो ज़्यादातर हाथ से लिखे wait की ज़रूरत हटाती हैं।
  • Waiting Strategies — SeleniumSelenium Projectब्राउज़र टेस्ट पेज से race क्यों करते हैं, और implicit व explicit waits WebDriver स्क्रिप्ट को ऐप के साथ कैसे सिंक करते हैं।
  • Best Practices — CypressCypress.ioसमर्पित एट्रिब्यूट से एलिमेंट चुनने, फ़िक्स्ड wait से बचने और टेस्ट को स्वतंत्र रखने पर Cypress की गाइडेंस।
  • Best Practices — PlaywrightMicrosoft (Playwright)यूज़र को दिखने वाला व्यवहार टेस्ट करें, टेस्ट अलग-थलग रखें, मज़बूत locator और web-first assertions अपनाएँ, और trace से डिबग करें।

अभ्यास

Release से पहले छह flaky टेस्ट का ट्रायेज करें

आपका काम

आप एक hotel booking web ऐप (काल्पनिक) के QA engineer हैं। Release 3.4 checkout पर promo codes जोड़ती है और दस दिन में live होती है। Playwright UI suite हर pull request पर तीन workers के साथ साझा staging environment पर चलता है, और रोज़ रात 02:30 रियाद समय पर, retries: 2 के साथ और बिना trace। पिछले दो हफ़्तों में 60 pull-request runs में से 21 retries के बाद ही हरे हुए, और छह टेस्ट ऐसे flag हुए हैं जो उसी commit पर fail होकर pass हुए। Material में configuration, अब तक जुटाए सबूतों के साथ छह टेस्ट, और टीम के दो notes हैं।

गाइड की causes की सूची, diagnosis के steps, fixes और retry व quarantine के नियमों के साथ काग़ज़ पर काम करें। एक developer retries बढ़ाने और एक टेस्ट skip करने का सुझाव देता है; release manager पूछती है कि हरे runs पर भरोसा किया जा सकता है या नहीं। एक टेस्ट में timezone converter काम आएगा। इसके लिए 30–45 मिनट रखें।

सामग्री
Hotel booking web ऐप (काल्पनिक) - कमरे खोजना, reserve करना, भुगतान, booking मैनेज करना
Release 3.4 checkout पर promo codes जोड़ती है। Go-live: रविवार 20 सितंबर 2026।
आज: गुरुवार 10 सितंबर।

UI suite: Playwright (TypeScript), 48 टेस्ट। हर pull request पर 3 workers के साथ साझा
staging environment पर चलता है, और रोज़ रात 02:30 रियाद समय पर एक nightly run।
Seed data हर run से पहले restore होता है; कोई भी टीम staging को कभी भी redeploy कर
सकती है। CI summary run को हरा मानती है अगर हर टेस्ट किसी भी attempt में pass हुआ हो।

playwright.config.ts (मौजूदा)
  retries: 2, workers: 3, fullyParallel: true,
  use: { trace: 'off', screenshot: 'off', video: 'off' }

पिछले दो हफ़्ते: release-3.4 branches पर 60 pull-request runs और 10 nightly runs।
60 में से 21 PR runs retries के बाद ही हरे हुए। वे टेस्ट जो उसी commit पर fail होकर
pass हुए, साथ में जाँच में अब तक जो मिला:

T1  booking.spec.ts > "Reserve" booking बनाता है                     60 में से 9 PR runs
    Error: "Booking confirmed" दिखा नहीं (timeout)। एक fail run पर हाथ से लिया गया
    trace: टेस्ट "Reserve" पर { force: true } के साथ क्लिक करता है जबकि बटन अभी
    disabled है और GET /api/quote pending है; क्लिक से कुछ नहीं होता। CI पर quote
    में 0.4-1.8 s लगते हैं, local पर 0.2 s। Blame: force: true 3 महीने पहले
    "timeout ठीक करने" के लिए जोड़ा गया।

T2  cancel.spec.ts > cancel करने से room nights खाली होती हैं       60 में से 6 PR runs
    सिर्फ़ तब fail होता है जब उसी run में पहले modify.spec.ts चला हो; अकेले pass।
    दोनों टेस्ट seed booking BK-1001 (room 204, 12-14 अक्टूबर) इस्तेमाल करते हैं।
    modify.spec.ts उसे 15-17 अक्टूबर पर ले जाता है। cancel.spec.ts उसे cancel करके
    "12-14 Oct released" की उम्मीद करता है; fail runs "15-17 Oct released" दिखाते हैं।

T3  signup.spec.ts > नया guest register कर सकता है                  60 में से 2 PR runs
    "Email already registered", सिर्फ़ तब जब दो workers एक साथ sign-up टेस्ट चलाएँ।
    फ़ाइल faker.seed(42) से शुरू होती है, इसलिए हर worker वही पहला email बनाता है:
    sara.guest@example.com। हर टेस्ट ख़त्म होने पर अपना account delete करता है।

T4  payment.spec.ts > test card से भुगतान                           60 में से 3 PR runs
    तीनों मंगलवार 8 सितंबर, 14:00-15:00, लगातार runs में: payment sandbox ने
    504 Gateway Timeout दिया। उसके status page पर 13:50-15:05 का incident दर्ज है।
    टेस्ट असली sandbox को call करता है।

T5  promo.spec.ts > promo code total अपडेट करता है                  60 में से 4 PR runs
    Total 432.00 SAR की जगह 480.00 SAR (code से पहले वाला) दिखाता है। कारण पक्का नहीं।
    हाथ से लिया गया एक trace: "Apply" एक बार क्लिक हुआ; GET /api/quote (जिसे date
    picker ने पहले भेजा था) ने POST /api/promo के बाद जवाब दिया, और पेज ने आख़िर में
    आए response को render किया। Local पर 20 में से 0 fail; network throttle करने पर
    (हर request में अतिरिक्त latency) 10 में से 7 fail।

T6  dates.spec.ts > check-in date default आज है       10 में से 10 nightly, 60 में से 0 PR
    Expected date runner पर new Date() से निकलती है, जो UTC में है; ऐप Asia/Riyadh में
    आज की तारीख़ दिखाता है। PR runs रियाद समय 08:00-18:00 के बीच होते हैं।

टीम के notes
  तारिक़ (developer): "retries: 3 कर दो और release के बाद तक promo.spec.ts skip करो।"
  हिंद (release manager): "क्या मैं 3.4 के हरे runs पर भरोसा कर सकती हूँ?"
  Owners  Booking और payments: लमा | Guest accounts: उमर | Search और calendar: यारा
चरण
  1. T1 से T6 को classify करें: गाइड से कारण, उसे सहारा देने वाला सबूत, और यह कि वह टेस्ट का defect है, environment या third-party की समस्या है, या प्रोडक्ट का defect। उन टेस्ट को चिह्नित करें जिनका failure बिल्कुल भी random नहीं है।
  2. T5 का कारण पक्का नहीं है। Diagnosis लिखें: उसे कैसे reproduce करेंगे, कौन-सी एक condition बदलेंगे, कौन-से सबूत पढ़ेंगे और back end से कैसे मिलाएँगे — फिर अपना निष्कर्ष और टेस्ट के साथ आप क्या करेंगे।
  3. हर टेस्ट का fix लिखें। कोई भी fix लंबा wait या retry नहीं हो सकता।
  4. आज का containment तय करें: कौन-से टेस्ट तुरंत ठीक करेंगे, कौन-से quarantine में जाएँगे (owner, ticket, due date, exit criterion), और किसे defect के रूप में रिपोर्ट करेंगे। फिर तारिक़ को जवाब दें।
  5. गाइड के अनुसार configuration और CI summary ठीक करें, हर टेस्ट और पूरे suite का flaky rate निकालें, top offenders बताएँ, और हिंद को जवाब दें।
मॉडल उत्तर दिखाएँ
मॉडल उत्तर

वर्गीकरण। T1 — timing और asynchrony, टेस्ट का defect। GET /api/quote के लौटने तक बटन disabled रहता है; { force: true } Playwright के actionability checks छोड़ देता है, इसलिए क्लिक disabled बटन पर dispatch होता है और कुछ नहीं होता। यह सिर्फ़ तब fail होता है जब quote धीमा हो, इसीलिए CI पर दिखता है (0.4–1.8 s) और local पर नहीं (0.2 s)। तीन महीने पहले के "fix" ने wait की समस्या को हल करने के बजाय छिपा दिया। T2 — shared state और टेस्ट का क्रम, दोनों टेस्ट का defect। दोनों एक ही seed booking BK-1001 को बदलते हैं, इसलिए नतीजा इस पर निर्भर है कि run में कौन-सा टेस्ट पहले चला: modify.spec.ts के बाद booking 15–17 अक्टूबर पर होती है, और उसे cancel करने से वही nights खाली होती हैं, 12–14 अक्टूबर नहीं। यह random दिखता है जबकि क्रम इसे पूरी तरह तय करता है।

T3 — टेस्ट डेटा की टक्कर (test data collision), टेस्ट का defect। faker.seed(42) "random" email को deterministic बना देता है: हर worker पहले sara.guest@example.com बनाता है, और जब पहला टेस्ट अभी वह account रखे हुए है तब उसे register करने वाला दूसरा worker uniqueness नियम तोड़ता है। यह सिर्फ़ तब fail होता है जब दो workers एक साथ sign-up टेस्ट तक पहुँचें, इसीलिए 60 में से 2, और दूसरे टेस्ट के अपना account delete करने के बाद retry pass हो जाता है। T4 — third-party service, न टेस्ट का defect न प्रोडक्ट का। दर्ज incident window (13:50–15:05) के अंदर तीन लगातार failures और उसके बाहर कोई नहीं — यह outage है, टेस्ट की flakiness नहीं; लेकिन यह दिखाता है कि blocking suite हर run में एक remote sandbox पर निर्भर है। कोई भी सबूत staging redeploys की ओर इशारा नहीं करता, फिर भी environment को ख़ारिज करने से पहले deploy के समय को failures के समय से मिलाएँ। T6 — समय और तारीख़ें, टेस्ट का defect। रियाद में 02:30 पिछले दिन का 23:30 UTC है, इसलिए runner UTC में new Date() से जो तारीख़ निकालता है वह कल की है, जबकि ऐप Asia/Riyadh में आज की तारीख़ दिखाता है; रियाद समय 08:00 और 18:00 के बीच दोनों एक होते हैं। यह 10 में से 10 nightly runs में fail होता है: बिल्कुल random नहीं, बल्कि एक ऐसी condition में deterministic जिसे PR runs कभी पूरा नहीं करते। यही बात T2 (क्रम) और T3 (एक साथ दो workers) पर, और आंशिक रूप से T1 (धीमा quote) पर भी लागू है: "flaky" का मतलब आमतौर पर यह है कि condition छिपी है, न कि कोई condition ही नहीं।

T5 — diagnosis। दोहराकर reproduce करें: spec को अकेले कई बार चलाएँ, जैसे npx playwright test tests/promo.spec.ts --repeat-each=20; local पर यह 20 में से 0 देता है जबकि CI पर 60 में से 4, यानी CI की परिस्थितियों में कुछ मायने रखता है। एक condition बदलें: network throttle करें और कुछ और न बदलें — rate 10 में से 7 हो जाता है, इसलिए कारण दो requests का आपसी timing है, डेटा या क्रम नहीं। सबूत पढ़ें: trace "Apply" पर एक क्लिक, POST /api/promo के बाद GET /api/quote का जवाब, और पेज का आख़िरी response render करना दिखाता है — एक पुराना quote discount वाले total के ऊपर लिख जाता है। Back end से मिलाएँ: server log में दोनों calls के request ids और timestamps देखें (time zones का ध्यान रखें: runner UTC इस्तेमाल करता है) ताकि पुष्टि हो कि quote request promo request के बाद ख़त्म हुई। निष्कर्ष: प्रोडक्ट में race condition (client पुराने responses को ignore नहीं करता), ठीक वही असली defect जिसे गाइड कभी quarantine न करने को कहती है। टेस्ट सही है; धीमे connection वाला guest valid code डालने के बाद 480.00 SAR देख सकता है। इसे लमा को trace, request ids, throttling में 10 में से 7 की rate, expected 432.00 SAR और actual 480.00 SAR के साथ रिपोर्ट करें; promo codes 3.4 की मुख्य feature हैं, इसलिए इसका fix 20 सितंबर से पहले ज़रूरी है। उसके बाद confirmation testing का मतलब है throttling में टेस्ट को कई बार दोहराना, एक हरा run नहीं।

Fixes — कोई sleep या retry नहीं। T1: { force: true } हटाएँ ताकि क्लिक बटन के enabled होने का auto-wait करे, और क्लिक से पहले signal को स्पष्ट करें: await expect(reserveButton).toBeEnabled(), या page.waitForResponse से /api/quote के response का इंतज़ार; फिर "Booking confirmed" पर web-first assertion नतीजा जाँचता है। T2: हर टेस्ट अपने setup में API से अपनी booking बनाए, नए browser context के साथ, और बाद में साफ़ करे; seed booking BK-1001 टेस्ट के लिए read-only हो या हट जाए। T3: faker.seed(42) हटाएँ और हर टेस्ट व हर worker के लिए unique values बनाएँ, जैसे ${testInfo.workerIndex}-${randomUUID()}@example.com या address में run id। T4: payment.spec.ts और बाक़ी UI टेस्ट में sandbox को stub करें — browser उसे call करता हो तो page.route से, back end करता हो तो mock server से — और असली sandbox के ख़िलाफ़ एक छोटा contract check अलग, non-blocking job में रखें जो अपनी रिपोर्ट अलग दे। T5: टेस्ट में कुछ ठीक नहीं करना; प्रोडक्ट fix के बाद टेस्ट regression check के रूप में रहता है। T6: expected date ऐप के time zone में Intl.DateTimeFormat और timeZone: 'Asia/Riyadh' से निकालें, या अगर पेज "आज" browser से लेता है तो Playwright की clock API (page.clock) से clock कंट्रोल करें और उस fixed समय की तारीख़ expect करें; 02:30 पर अगले nightly runs fix की पुष्टि करते हैं।

आज का containment। तुरंत fix, बिना quarantine — हर एक किसी एक टेस्ट के अंदर छोटा बदलाव है: T1 (लमा), T3 (उमर) और T6 (यारा); merge से पहले हर एक को --repeat-each=50 के साथ चलाएँ। गाइड की शर्तों पर quarantine: T2 (owner लमा, ticket, due date ज़्यादा से ज़्यादा गुरुवार 17 सितंबर — रविवार के go-live से पहले का आख़िरी working day, और दस working days की सीमा के काफ़ी अंदर — exit rewrite के बाद --repeat-each के साथ लगातार 50 passes पर) और T4 (owner लमा, ticket, वही due date, exit तब जब sandbox stub हो जाए और contract check अपनी job में चले)। दोनों non-blocking job में चलते रहते हैं और साप्ताहिक सूची में रहते हैं। रिपोर्ट, कभी quarantine नहीं: T5 ऊपर के सबूतों के साथ लमा के लिए defect बनता है, और promo.spec.ts blocking suite में रहता है; defect खुला रहने तक उसके failures एक असली कारण से दिखते रहते हैं — लाल या flaky के रूप में चिह्नित। तारिक़ को जवाब: retries एक भी कारण ठीक किए बिना पहले ही 21 runs को हरा कर चुके हैं; retries: 3 और ज़्यादा छिपाएगा, हर fail टेस्ट में एक और attempt जोड़ेगा, T6 के लिए कुछ नहीं करेगा (वह clock पर चलता है, संयोग पर नहीं), और T5 को छिपाए रखेगा — वह अकेला failure जो 3.4 का defect है। promo.spec.ts skip करना उस अकेले check को हटा देता है जिसने इसे पकड़ा। नीति इसका उल्टा है: CI में ज़्यादा से ज़्यादा एक retry, local पर कोई नहीं, और retry में pass होने वाला failure flaky के रूप में रिपोर्ट होता है, passed के रूप में नहीं।

Configuration और माप। playwright.config.ts को गाइड की तरह retries: process.env.CI ? 1 : 0, trace: 'on-first-retry', screenshot: 'only-on-failure' और video: 'retain-on-failure' पर ले जाएँ, ताकि हर flaky failure हाथ से लिए trace के बजाय एक screenshot और video छोड़े, और उसका retry एक trace। CI summary बदलें: जिस run को retry चाहिए वह टेस्ट नामों के साथ flaky रिपोर्ट हो — Playwright यह status पहले से देता है। 60 PR runs पर हर टेस्ट का flaky rate: T1 9/60 = 15%, T2 6/60 = 10%, T5 4/60 ≈ 6.7%, T4 3/60 = 5% (एक incident), T3 2/60 ≈ 3.3%; T6 nightly runs का 100% और PR runs का 0%। Suite स्तर पर: 60 में से 21 PR runs को retry चाहिए था (35%), जिसकी वजह 60 × 48 = 2,880 test executions में 24 flaky नतीजे (लगभग 0.8%) हैं — हर टेस्ट का छोटा rate भी एक-तिहाई runs को छूने के लिए काफ़ी है। Top offenders: PR runs के 24 flaky failures में से 15 (62.5%) T1 और T2 के हैं, इसलिए दो टेस्ट ठीक करने से ज़्यादातर शोर हट जाता है। हर quarantined टेस्ट पर time-to-fix की घड़ी आज से शुरू करें और सूची की हर हफ़्ते review करें। हिंद को जवाब: अभी नहीं। 60 में से 21 PR runs (35%) सिर्फ़ retries की वजह से हरे थे, बिना trace के, और retries ने promo feature का एक असली defect छिपाया; 3.4 के लिए suite तब भरोसेमंद है जब T1, T3 और T6 ठीक हों, T2 और T4 17 सितंबर तक quarantine से बाहर हों, T5 ठीक होकर confirm हो, और summary flaky नतीजे दिखाए — तब release-candidate run बिना किसी flaky नतीजे के हरा होना चाहिए।

अगर आपके जवाब अलग हैं, तो उन्हें गाइड के नियमों से जाँचें: हर fix किसी condition का इंतज़ार करता है या साझा निर्भरता हटाता है, समय का इंतज़ार कभी नहीं; retries और quarantine containment हैं, इलाज नहीं; जो failure प्रोडक्ट defect हो सकता है उसकी जाँच टेस्ट को दोष देने से पहले होती है। कारण के साथ अलग चुनाव ठीक है — जैसे quote का wait लिखे जाने तक T1 को एक दिन quarantine करना — बशर्ते उसका owner, ticket और due date हो।

इस topic में आपकी प्रगति

QA रोडमैप का हिस्सा

इस गाइड में बताए गए टूल्स

टेस्ट अकाउंट के लिए फ़ेक यूज़र रिकॉर्ड (नाम, username, ईमेल, पासवर्ड, avatar seed, role) जनरेट करें।

टेस्ट डेटा

सिंथेटिक टेस्ट डेटा की एक ही जगह पर फ़ैक्टरी: users, customers, companies, पते, संख्याएँ, तारीख़ें और स्ट्रिंग — JSON, CSV, SQL या XML में।

टेस्ट डेटा

HTTP रिक्वेस्ट (method, URL, हेडर, auth, बॉडी) बनाएँ और भेजें, फिर रिस्पॉन्स जाँचें — आपके ब्राउज़र में हल्का-फुल्का Postman।

API टेस्टिंग

Mutqan Soft कैसे मदद कर सकता है

और गाइड

और गाइड
ऑटोमेशन

UI टेस्ट के लिए Locator रणनीतियाँ

UI टेस्ट के locators कैसे चुनें: पहले role और label, फिर test ids, CSS और XPath; dynamic ids, iframes, shadow DOM, anti-patterns और checklist।

12 मिनट पढ़ने का समय
ऑटोमेशन

CI/CD पाइपलाइन में टेस्टिंग

CI/CD पाइपलाइन में टेस्टिंग कैसे होती है: टेस्ट स्टेज, तेज़ फ़ीडबैक का क्रम, क्वालिटी गेट, JUnit रिपोर्ट, शार्डिंग, flaky टेस्ट और फ़ेलियर ट्राइएज।

16 मिनट पढ़ने का समय
टेस्ट डिज़ाइन

स्मोक, सैनिटी और रिग्रेशन टेस्टिंग में अंतर

Smoke, sanity और regression टेस्टिंग की तुलना: दायरा, समय, गहराई और ऑटोमेशन, "sanity" शब्द अस्पष्ट क्यों है, और regression टेस्ट कैसे चुनें।

11 मिनट पढ़ने का समय
ऑटोमेशन

मोबाइल टेस्ट ऑटोमेशन की व्याख्या

मोबाइल टेस्ट ऑटोमेशन कैसे काम करता है: Appium, Espresso और XCUITest की तुलना, accessibility-id locators, flakiness के स्रोत, device farm और CI pipeline।

12 मिनट पढ़ने का समय
ऑटोमेशन

UI टेस्ट ऑटोमेशन

UI टेस्ट ऑटोमेशन व्यवहार में: फ़्रेमवर्क की परतें, Selenium, Playwright और Cypress, locators, waits, assertions, page objects, टेस्ट डेटा और CI।

16 मिनट पढ़ने का समय
टेस्ट डिज़ाइन

एंड-टू-एंड प्रोडक्ट क्वालिटी एश्योरेंस

एंड-टू-एंड QA में क्या आता है — आवश्यकता समीक्षा, टेस्ट डिज़ाइन, फ़ंक्शनल, API, परफ़ॉर्मेंस और सुरक्षा टेस्टिंग, रिलीज़ गेट और मेट्रिक्स — और इसे कैसे चलाएँ।

11 मिनट पढ़ने का समय