Coverage That Proves Features Work

Flow-Based Coverage
Definitive Proof

A passing flow proves success in a way that test suites cannot.
Each flow is a complete user journey — start to finish — not isolated tests.

1 script per user journey

Not 8–12 fragments

Passing flow = proof the feature works

Not just that parts rendered

Failures pinpoint exactly which step broke

Not cascading noise

Flows Fix The Fragmented Test Problem

A green CI run is not the same thing as a working product. Fragmented test suites can pass completely while critical user journeys are broken.

Real Scenario: Checkout is broken. CI is green.
Fragmented suite — all passing
Cart renders product name
Cart renders correct price
Address form renders
Address form validates email
Shipping options appear
Payment form renders
Place Order button is clickable
Success page renders

Checkout is broken

An API contract change broke the state handoff between cart and checkout. Every slice still passes. The integration is silent.

“A suite of 400 tests can pass perfectly. Checkout can still be broken.”

The unit of measurement doesn't match the unit of value. Counting tests is not the same as verifying journeys. Each isolated test checks a slice — none of them answer the only question that matters: does the feature work?

Anatomy of a Flow

What a Flow Actually Is

A flow is defined by three things — not by the tool, the language, or the number of assertions. Answer these three questions for any feature and you have a flow.

1

What does the user want to accomplish?

This defines the flow's scope and name. e.g. “Complete a purchase as a guest.”

2

What is the starting state?

Where does the script begin? e.g. “On the product page, not logged in.”

3

What is the observable, measurable outcome?

The assertion that makes the result definitive. e.g. “The ‘Order Confirmed’ page appears with an order ID.”

The key rule: a flow cannot produce a false positive. If the script reaches the measurable outcome without failing any step, the feature works end to end, right now. No isolated check can make that claim.

guest-checkout-flow.spec.tsTypeScript · Playwright
test.describe('Guest Checkout Flow', () => {
  test('completes checkout end to end', async ({ page }) => {

    await test.step('Add product to cart', async () => {
      await page.goto('/products/sneakers');
      await page.getByRole('button', { name: 'Add to Cart' }).click();
      await expect(page.getByTestId('cart-count')).toHaveText('1');
    });

    await test.step('Proceed through checkout', async () => {
      await page.goto('/checkout');
      await page.getByTestId('shipping-name').fill('Jane Doe');
      await page.getByTestId('shipping-address').fill('123 Main St');
      await page.getByRole('button', { name: 'Continue' }).click();
    });

    await test.step('Complete payment', async () => {
      await page.getByTestId('card-number').fill('4242424242424242');
      await page.getByRole('button', { name: 'Place Order' }).click();
    });

    await test.step('Verify order confirmed', async () => {
      await expect(page.getByText('Order Confirmed')).toBeVisible();
      await expect(page.getByTestId('order-id')).toBeVisible();
    });

  });
});
Standard Playwright · One journey, one answer

What a Flow Gives You

A flow is a single script that runs a complete user journey — real browser, real API calls, real session — from entry to measurable outcome. Its result is unambiguous.

Guest Checkout Flow — 1 script, complete signal
1
Navigate to product page, add to cart
2
Proceed to checkout, fill shipping form
3
Select shipping option
4
Enter payment details, submit order
Assert "Order Confirmed" page with order ID

Flow passes

Checkout works. Ship with confidence.

Flow fails at step 3

Shipping selector broke. Exact location, instant diagnosis.

Definitive signal

If the flow passes, the feature works — end to end, right now, in the environment where it ran. No fragmented suite can make that statement.

Precise failure attribution

When a flow fails, the step name, screenshot, and trace point to one location. No cascading noise from 12 tests sharing the same root cause.

Minimal maintenance surface

One flow to maintain instead of twelve. When your UI changes, one script updates. Selector changes live in a single page object.

Catches integration bugs

State propagation failures, session edge cases, and API contract mismatches between steps only appear in realistic navigation sequences. Flows run them. Slices skip them.

Business-legible coverage

A list of flows — Login Flow, Checkout Flow, Subscription Upgrade Flow — answers the coverage question any stakeholder can ask. “340 tests passing” answers nothing. Flow-based coverage maps directly to the features that generate revenue, making QA conversations into product conversations.

Flows vs. Fragmented Tests

The difference isn't in the technology. It's in what the result actually tells you.

Dimension
Fragmented Tests
Flow-Based Coverage
Does a passing result prove the feature works?No — parts pass while the journey can be brokenYes — a passing flow proves the journey works
Are integration bugs between steps caught?No — each test mocks what it doesn’t ownYes — the full sequence runs without mocking
Scripts per user journey8–12 fragments1 flow
Updates when a UI element changes8–12 updates across multiple files1 update in one place
Readable by non-engineers?No — requires decoding test runner output"Checkout Flow: passing" is self-explanatory
Can the suite accumulate false confidence?Yes — grows toward entropy with every sprintNo — coverage is always journey-mapped

Which Journeys Deserve a Flow?

Not all user journeys are equally important to automate. Classify by what breaks when they fail.

Priority 1

Revenue-critical

If this breaks, you stop earning.

  • Checkout
  • Subscription upgrade
  • Payment method update
Priority 2

Retention-critical

If this breaks, users churn.

  • Login
  • Core product workflow
  • Daily-use features
Priority 3

Growth-critical

If this breaks, acquisition slows.

  • Sign-up
  • Onboarding
  • Email verification
Priority 4

Support-intensive

If this breaks, your queue fills.

  • Password reset
  • Invoice download
  • Data export

How Many Flows Do You Need?

A 3-step framework for translating your app's user goals into a flow count.

1

List user goals, not features

Users come to your product to accomplish things, not to use features. Write down every primary user goal. “User runs a report” is a goal. “Report dropdown renders” is not.

2

Add variants for meaningful path differences

Each significant variant gets its own flow. Guest checkout and authenticated checkout are two different journeys, even though both end at “Order Confirmed.” Invalid-credentials login is a distinct variant worth its own flow.

3

Bundle simple variants into one script

If Admin login, Supervisor login, and User login all follow the same form and fit within a single script's scope, that's 1 flow — not 3. Bundling keeps your count lean without losing coverage.

Rule of thumb: most apps with 5–10 core user goals need 20–50 flows for meaningful journey coverage. Start with revenue-critical and retention-critical paths first, then expand outward.

example — SaaS product

User GoalVariantsFlows
Sign upEmail + Google2
LoginEmail / Google / MFAbundled1
Connect data sourceStandard flow1
Run a reportCreate + share2
Invite a teammateAdmin role1
Upgrade planFree → Pro1
Password resetStandard flow1
Total9

7 user goals → 9 flows. Add edge cases and you'd reach ~15–20 for full confidence.

Common Questions About Flows

Definitions, comparisons, and clarifications on the flow model.

From the Blog

“Your Tests Are Passing. Your Feature Is Broken.”

A deeper look at why fragmented test suites produce false confidence — and the five concrete reasons flows are categorically different from any suite of isolated checks.

Read the Article

See what flow coverage looks like on a real product

We'll map your critical user journeys live and show you exactly what a flow covers that your current test suite misses.