Playwright Intro - discussion (2023-03-11)
Playwright is one of those tools that changes how you think about correctness: it forces you to accept that your app is a system with timing, navigation, and user posture. I'm curious how people are combining E2E with the forum's idea of route-flow narration and evidence keys.
Do you treat E2E tests as user-only (roles/text), or do you also assert on evidence keys to make failures explainable? How do you keep E2E suites fast without turning them into vague smoke tests? What do you log in CI so a failing run is debuggable without re-running locally?
Comments (12)
Back to latestWe assert on evidence keys for lane/source, and roles/text for content.
It makes failures readable.
Our CI output is basically a tips log plus a screenshot with evidence visible:
txt
[tips] e2e=checkout step=enter lane=pending evidence=lane:pending
[tips] e2e=checkout step=resolve lane=ok evidence=lane:ok
Then we attach the screenshot artifact. The screenshot is meaningful because evidence is rendered on the shell.
Concrete alternative: don't assert on data-* in E2E, only use user-perceivable behavior.
I get the argument, but when a test flakes, you want something that tells you whether you're stuck pending, showing stale cache, or in an error lane.
Same. We kept evidence assertions minimal (just lanes + source) and it paid for itself immediately in flake triage.
If your evidence is truthful, it's not an implementation detail, it's an observation.
Docs tie-in: E2E complements the docs' testing guidance, especially when you treat route flows as first-class and make state observable.
Related: Testing and Debugging and Routing and Navigation.
We keep suites fast by splitting them: a few full route-flow tests, then lots of tiny evidence sanity tests.
The tiny tests just assert the app can boot and render lane:ok for key routes. They're cheap and catch big regressions.
We made flake debugging less painful by always recording traces on failure and printing a single line of contract context.
The trace tells you timing; the evidence tells you posture.
A tiny Playwright pattern that helped: wait on evidence, not timeouts.
ts
await expect(page.locator('[data-evidence]')).toContainText('lane:ok');
When you wait on a contract, the tests are less flaky than when you wait on a timer.
Short take: if your E2E tests are slow, your routes are doing too much on enter.
Long-form: E2E becomes maintainable when it mirrors how you think about the app: identity + posture + motion.
Playwright gives you motion and timing; the app must provide identity and posture (evidence). If either side is missing, your suite turns into a pile of sleeps and screenshot diffs.
We kept our suite smaller by moving most logic into RTL tests and using Playwright for the critical flows only.
E2E is expensive; spend it where it buys confidence.
If you want CI logs to be useful, print a tips line at each route boundary in the test output.
Takeaway: Playwright doesn't solve flakiness by itself. Contract evidence does.
Once the app narrates its lanes, Playwright tests become readable and stable.