๐Ÿณ IntuitiveFE
Login
โ† All concepts

Testing Pyramid & E2E Strategy

โฑ๏ธ ~3-minute bite ยท solve the sandbox to master

0%lesson
๐Ÿง’

5-Year-Old Metaphor

โ€” The physical, real-world picture. No jargon.

๐Ÿ•ธ๏ธ Tests are safety nets โ€” the pyramid shape tells you how dense each layer should be.

The safety net analogy

Unit tests = fine mesh net at the bottom. Catches small bugs (logic errors in individual functions) instantly. Very cheap โ€” thousands of them are fine.

Integration tests = medium mesh net in the middle. Catches bugs where components interact incorrectly. Moderate cost โ€” hundreds is reasonable.

E2E tests= coarse mesh net at the top. Only catches things that slip through both layers โ€” full user journey failures. Very expensive โ€” tens is the limit. Don't try to catch everything here.

The Ice Cream Cone (anti-pattern)

No unit tests. A few integration tests. Hundreds of E2E tests. CI takes 3 hours. Tests are flaky โ€” 10% fail on any given run for no clear reason. Developers ignore failures. The suite exists but provides no confidence. This is the most common testing anti-pattern in real codebases.

๐ŸŽ›๏ธ

Interactive Sandbox

โ€” Move something, see it react instantly.

Testing Layer

Unit Tests

70%+ of tests
Speed: < 1ms each
Cost: Cheapest to write & maintain
Tools: VitestJest

Test a pure function: formatCurrency(1234.5, 'USD') === '$1,234.50'

Good for

Pure functions, business logic, edge cases

Bad for

Integration bugs, UI rendering, real API behavior

Integration Tests

20% of tests
Speed: 10โ€“100ms each
Cost: Moderate โ€” needs MSW or test server
Tools: React Testing LibraryMSWVitest

Render <LoginForm />, fill email/password, click submit, assert API called and redirect occurs

Good for

Component behavior, form flows, API integration

Bad for

Full user journeys, browser-specific bugs

E2E Tests

10% of tests (critical paths only)
Speed: 5โ€“30s each
Cost: Most expensive โ€” slow, flaky, hard to maintain
Tools: PlaywrightCypress

Navigate to /signup, fill form, verify email, log in โ€” real browser, real HTTP

Good for

Critical user journeys, cross-browser, auth flows

Bad for

Edge cases, rapid iteration, every code path

โš ๏ธ Gotcha: The ice cream cone anti-pattern: few unit tests, some integration, many E2E. Suite takes 2 hours to run. Flaky tests are ignored. E2E is the most expensive safety net โ€” use it sparingly for critical paths only.
๐Ÿ’ก Insight: The pyramid's shape is intentional: the base (unit) is cheap and fast โ€” run them on every save. The apex (E2E) is expensive and slow โ€” run them on PRs only. Invert the pyramid and your CI becomes unusable.
Visited:๐Ÿ”๏ธ๐Ÿ”ฌ๐Ÿ”—๐ŸŒ๐Ÿ“š
๐ŸŽฏ

Challenge

Visit all 5 testing patterns. Understand when to use each test layer and how to write effective tests.

Try it
๐ŸŽฏ

Why Should I Care?

โ€” The exact interview question + the bug it kills.

Interview questions

Q: What is the test pyramid and why does it matter?

The test pyramid describes the ideal distribution: many fast, cheap unit tests at the base; fewer, slower integration tests in the middle; very few expensive E2E tests at the top. It matters because speed = developer feedback loops. A test suite that runs in 30 seconds gets run constantly. A suite that runs in 30 minutes gets skipped. The pyramid keeps the suite fast by keeping expensive tests rare.

Q: What is the difference between mock, stub, and spy?

Stub: a replacement with hard-coded return values โ€” replaces real implementation, returns predictable data. Mock: a stub that also verifies it was called correctly โ€” asserts that specific calls happened with expected arguments. Spy: wraps a real implementation and records calls without replacing behavior โ€” useful to verify a real function was called. In Jest/Vitest: jest.fn() creates a mock, jest.spyOn() creates a spy.

Q: How does RTL's philosophy differ from Enzyme?

Enzyme tests the React component tree โ€” you access component state, call lifecycle methods directly, and inspect internal structure. RTL tests the rendered DOM and user interactions โ€” you query by ARIA role and label, simulate user events, and assert on what the user sees. Enzyme broke constantly during React upgrades because it depended on React internals. RTL's DOM-based approach is decoupled from React implementation details.

๐Ÿ”ฌ

The Deep Dive

โ€” Spec refs, engine internals, the minutiae.

MSW setup for tests

js
1// src/mocks/handlers.ts
2import { http, HttpResponse } from 'msw';
3ย 
4export const handlers = [
5 http.get('/api/user', () =>
6 HttpResponse.json({ id: '1', name: 'Alice' })
7 ),
8 http.post('/api/login', async ({ request }) => {
9 const { email } = await request.json();
10 if (email === 'valid@test.com') {
11 return HttpResponse.json({ token: 'abc123' });
12 }
13 return HttpResponse.json({ error: 'Invalid' }, { status: 401 });
14 }),
15];
16ย 
17// src/mocks/server.ts
18import { setupServer } from 'msw/node';
19import { handlers } from './handlers';
20export const server = setupServer(...handlers);
21ย 
22// vitest.setup.ts
23import { server } from './src/mocks/server';
24beforeAll(() => server.listen());
25afterEach(() => server.resetHandlers());
26afterAll(() => server.close());

Coverage metrics explained

MetricWhat it measuresLimitation
StatementEvery line executedIgnores branches
BranchEvery if/else path takenBest proxy for logic coverage
FunctionEvery function calledEasy to game โ€” empty test calls function
LineEvery line hit (excludes blanks)Similar to statement

Branch coverage is the most meaningful metric โ€” it ensures both sides of every conditional are tested. 80% branch coverage is a reasonable gate. 100% is usually not worth the effort (test every null check?).

Vitest vs Jest

Jest

  • Industry standard, massive ecosystem
  • Own module resolution (sometimes surprising)
  • Slower on large codebases
  • CJS-first, ESM support improving

Vitest

  • Vite-native, shares vite.config.ts
  • 10โ€“20x faster with HMR test rerun
  • ESM-first, TypeScript natively
  • Jest-compatible API โ€” easy migration
๐ŸŽค

Interview Questions

โ€” Real questions from real interviews โ€” with answers.

Over-relying on E2E tests made our CI suite too slow and flaky to trust.

Measure the bug rate in untested vs tested files and present the correlation.

Unit test pure logic; integration test user-facing behavior; skip trivial plumbing.

MSW intercepts at the network layer โ€” your real fetch code runs, the response is controlled.

Quarantine immediately, fix root cause within one sprint, delete if unrepairable.

Branch coverage over line coverage; 80% is a reasonable gate but quality beats quantity.

๐ŸŽฎ

Memory Game

โ€” Quick quiz โ€” lock the concept in long-term memory.
1/4

What is a 'snapshot test' and when should it be avoided?