Lesson 10 / الدرس 10
Waiting, and the flaky test / الانتظار، والاختبار المتقلّب
A flaky test is one that passes and fails without the product changing. It is the single thing most likely to destroy a team's trust in automation, and almost all of it comes from one mistake: acting before the page is ready.
الاختبار المتقلّب هو الذي ينجح ويرسب دون أن يتغير المنتج. وهو أكثر شيء يُرجَّح أن يهدم ثقة فريق بالأتمتة، وجُلّه يأتي من خطأ واحد: التصرّف قبل أن تكون الصفحة جاهزة.
Your code runs in microseconds. The browser needs to fetch, parse, render, and often wait for a request to come back before the thing you want even exists. A test that clicks before the button is there does not fail helpfully — it fails on the machine that happened to be slow that morning, which is how a suite becomes something people re-run instead of read.
Never sleep. Wait for the condition
The instinct is to add a pause — wait two seconds, then click. It works on your machine, and it is the worst possible fix. Two seconds is simultaneously too long on every passing run and too short on the one slow run that matters. A hundred such pauses is three minutes added to every build, and the flakiness is still there. Wait for the thing itself instead: the element to be visible, the URL to change, the request to finish.
// Wrong. Passes on your laptop, fails in the pipeline, and adds 2s either way.
await page.waitForTimeout(2000);
await page.getByRole('button', { name: 'Save' }).click();
// Right. Waits exactly as long as it needs to, and no longer.
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByText('Saved')).toBeVisible();
// Right, when the thing you are waiting for is a request:
await Promise.all([
page.waitForResponse(r => r.url().includes('/orders') && r.status() === 201),
page.getByRole('button', { name: 'Place order' }).click(),
]);
The other causes, in order
-
Tests that share data. One deletes the account another signs in with. They pass alone and fail together, or fail only when run in a different order. اختبارات تتشارك البيانات. فأحدها يحذف الحساب الذي يدخل به آخر. فينجحان منفردين ويرسبان معًا، أو يرسبان حين يجريان بترتيب مختلف.
-
Time. A test that uses today's date, or breaks at midnight, or assumes a month has 30 days. الوقت. اختبار يستخدم تاريخ اليوم، أو ينكسر عند منتصف الليل، أو يفترض أن الشهر ثلاثون يومًا.
-
Real external services. A payment provider's sandbox is not your test's responsibility, and its bad afternoon becomes your red build. خدمات خارجية حقيقية. فبيئة تجربة مزوّد الدفع ليست مسؤولية اختبارك، وعصر يومها السيئ يصير بناءك الأحمر.
-
Animation. An element that is present but still sliding into place can be clicked in the wrong spot. الحركة. فالعنصر الموجود وهو ما زال ينزلق إلى موضعه يمكن أن يُضغط في المكان الخطأ.
Check yourself / اختبر نفسك
1. Why is a fixed two-second pause the wrong way to fix a timing problem?
A fixed wait is wrong in both directions at once. It taxes every green run and still loses the race on a slow machine, so the flakiness survives and the suite gets slower.
2. Two tests pass alone and fail when run together. What is the likely cause?
Passing in isolation and failing together is the signature of shared state. Each test needs to create what it needs and not depend on what another left behind — which is the next lesson.
3. What is the real cost of leaving a known-flaky test in the suite?
The damage is to the signal, not the schedule. Once "just re-run it" becomes the habit, a red build stops meaning anything — and the suite is then decoration that costs money to maintain.
Score / النتيجة: 0 / 3