Nexus
← All articles
10 March 2026·8 min read

Why Your Playwright Tests Are Flaky (And How to Fix Them)

Flaky tests are worse than no tests — they create noise your team learns to ignore. Here are the five most common causes of Playwright flakiness and exactly how to fix each one.

Most teams come to us with the same complaint: "Our tests pass locally and fail in CI," or "We have to re-run the suite three times before we trust the result." Flaky tests are worse than no tests. A test that sometimes fails isn't telling you anything useful — it's just creating noise that your team learns to ignore. And once your engineers start ignoring test failures, you've lost the entire point of automation.

Here are the five causes we see most often, and how to fix each one.

The five most common causes — and the fix for each

1. You're not waiting for the right thing

The most common cause of Playwright flakiness is waiting for the wrong signal. page.waitForTimeout(2000) is not a solution — it's a guess. Sometimes your page loads in 1.8 seconds, sometimes in 2.3 seconds, and your test fails for no apparent reason.

Fix: Replace all timeout-based waits with condition-based waits. page.waitForSelector(), expect(locator).toBeVisible(), page.waitForResponse() — these wait until something is actually true, not until an arbitrary clock ticks over.

2. Tests that share state

If your tests run in a fixed order and each one depends on the previous test having set something up, you have state coupling. Test 47 fails because test 23 didn't clean up after itself. This is particularly common with database state, cookies, and local storage.

Fix: Each test should create its own state and clean it up. Use beforeEach hooks for setup and afterEach for teardown. Treat each test as if it's the only test in the suite.

3. Environment differences

"Works on my machine" is a QA cliché for a reason. Playwright tests that pass locally and fail in CI are almost always caused by environment differences: different screen resolutions, different network latency, different base URLs, or missing environment variables.

Fix: Use playwright.config.ts to lock down your test environment. Set an explicit viewport, use baseURL from environment variables, and run your tests locally against the same Docker environment your CI uses. Eliminate environment differences as a variable entirely.

4. Overly brittle selectors

If your test targets elements with page.locator('.main-container > div:nth-child(3) > button'), it will break the moment a developer adds a wrapper div. This is the CSS selector equivalent of painting yourself into a corner.

Fix: Use Playwright's recommended locator strategies in priority order: getByRole(), getByLabel(), getByTestId(). These target semantic meaning and explicit test IDs, not structural position. Add data-testid attributes to key elements as part of your development process — make it a PR checklist item.

5. Uncaught async errors

Playwright runs asynchronously, and if you're not properly awaiting assertions, you can get false positives (tests that pass even when they should fail) or false negatives that fail intermittently based on timing.

Fix: Always await your assertions. Use await expect(locator).toBeVisible() not expect(locator).toBeVisible(). Enable strict mode in your Playwright config to catch these at the framework level rather than discovering them in production.

How to diagnose which problem you have

Run your suite 10 times without changing anything. Record which tests fail and how often. Tests that fail consistently are bugs in the test or the application. Tests that fail intermittently are flaky. Look at the failure messages — "timeout exceeded" points to waits; "element not found" points to selectors or state; "element is not stable" points to animation or race conditions.

Once you've identified the category, apply the corresponding fix above. Most teams find that 80% of their flakiness traces to one or two root causes — fix those and the rest of the suite stabilises.

If this sounds like your test suite right now, we've fixed this exact problem dozens of times. A short engagement can turn an unreliable suite into one your team actually trusts.

Get in touch to talk through your situation

WORK WITH NEXUS

Got a QA problem? Let's talk about it.