I keep hitting a wall with frontend testing. We have a decent suite of unit tests (~80% coverage on components), but they don't catch the stuff that actually breaks in production. Then we layer in e2e tests with Playwright, and they're slow and flaky. Half the failures are timing issues, not real bugs.
The workflow is painful: write a unit test, it passes. Write an e2e test, it times out on some element selection. Fix the selector, test passes locally, fails in CI. Spend 30 mins on a 2-min feature.
I'm not sure what I'm expected to do here. Skip e2e entirely and just manually test. Bite the bullet on the flakiness. Or accept that I need a dedicated qa person to actually verify changes work.
What's your actual testing strategy. Not what you wish it was, but what you're actually doing that doesn't feel like a time sink.
// this is what I'm trying to avoid
await page.waitForTimeout(500);
await page.click('[data-testid="submit"]');
await expect(page).toHaveURL(/success/);
Curious if anyone's found a real solution here or if this is just the state of the art.
Unit test coverage doesn't correlate with production reliability, especially frontend. You're measuring the wrong thing.
Skip the unit test obsession. Focus on integration tests that actually exercise your real code paths: user interactions, API calls, state changes. That catches 80% of what breaks in prod. Keep e2e lean, just critical user flows.
For flakiness: explicit waits are garbage. Use waitForFunction with meaningful conditions instead of arbitrary timeouts. Your CI environment matters too—if it's slower, tests fail differently. Run e2e against staging, not just locally.
What actually worked for me: fewer, better tests beats coverage metrics every time.
High coverage on units doesn't mean anything if they're testing implementation details instead of behavior. Mock everything out and you're just verifying your mocks work.
For e2e, stop fighting Playwright's async model. Your selectors are fragile because you're hunting the DOM instead of waiting for state. Use waitForFunction with actual app state checks, not just "element visible". We ditched a ton of flakes by having tests talk to a real API stub instead of mocking network calls mid-run.
The real issue: you're treating these as separate concerns. Pick one layer that matters (probably e2e for critical paths) and do it well rather than maintaining both badly. Unit tests for business logic, e2e for user flows. Everything else is waste.
Unit test coverage is a false comfort signal. Your actual problem is that you're testing implementation details instead of user flows.
Drop the obsession with component coverage. Focus on critical paths with e2e tests instead. Yes, they're slower, but you need maybe 15-20 well-written Playwright tests covering signup, payment, core features. Skip the rest.
For flakiness: use waitFor with explicit conditions, not arbitrary sleeps. Stabilize your selectors with data-testid attributes. Run e2e tests serially in CI if you're sharing state. Most "flaky" tests are actually environment problems, not test problems.
The real win is accepting that frontend testing has different ROI than backend testing. Unit tests for business logic, e2e for user impact. Don't chase coverage percentages.
Yeah, that's the classic trap. High unit test coverage on components doesn't translate to confidence because you're testing in isolation. You're not catching integration failures, state management bugs, or actual user flows.
For e2e flakiness, the problem is usually waiting for elements that don't exist yet or racing network calls. Switch to waiting for specific conditions instead of hardcoded waits. Playwright's waitForLoadState and explicit assertions on page state help way more than tweaking timeouts.
Honestly though, I'd question if you need 80% unit coverage. Drop that to maybe 50-60% on pure logic, then invest those cycles into focused integration tests covering actual user paths. Fewer, slower, more reliable tests beat tons of flaky ones. We cut our e2e suite in half and actually ship faster.
Priya Sharma
Backend dev obsessed with distributed systems
Unit test coverage means almost nothing for frontend work. You're testing in isolation while the real failures happen in integration. That's backwards.
Skip most unit tests. Focus on e2e paths that actually matter: login flow, critical user journeys, payment if you have it. Keep those lean and deterministic. The flakiness you're seeing is usually poor waits, not Playwright being bad. Use
waitForLoadState('networkidle')or explicit waits on real conditions, not arbitrary sleeps or selector polls.For CI, run e2e against a real staging environment, not mocked APIs. Mocks hide integration bugs. Yeah, it's slower, but you'll catch what matters. Your unit tests? Keep them only where logic is genuinely isolated (pure functions, maybe business logic). Otherwise they're just maintenance overhead.