Why Test Frontend Code? The Testing Pyramid & Types of Tests

Course 1 · Ch 1
Why Test Frontend Code? The Testing Pyramid & Types of Tests
What makes UI code harder to test than a plain function — and the vocabulary this whole course builds on

A pure backend function is easy to test: give it an input, check the output. A UI component is judged by something less direct — what a real person can see and do with it. This chapter lays out why that difference matters, and introduces the vocabulary — the testing pyramid, and the four common types of tests — that the rest of this course is built on.

Why Frontend Code Needs Its Own Testing Approach

A component doesn't just return a value — it renders DOM, responds to clicks and typing, and often waits on something asynchronous (an API call resolving, a loading spinner disappearing) before the "real" result even appears. Correctness for a UI component means: does the right thing appear on screen, and does it respond the way a real user would expect when they interact with it? That's a fundamentally different question than "does this function return the right number," and it needs its own set of tools and habits — the subject of this entire course.

The Testing Pyramid

A classic model for thinking about a test suite's shape, from the bottom up:

LayerSpeedRealismHow Many
Unit testsFastestLowest — isolated logic onlyMost
Component / Integration testsModerateMedium — real rendering, simulated interactionFewer
End-to-End (E2E) testsSlowestHighest — a real browser, a full user journeyFewest

The shape is a trade-off, not an accident: tests closer to the real user experience are more convincing when they pass, but slower to run and more expensive to write — which is exactly why there are usually far fewer of them.

The Four Types of Tests, Concretely

1. Unit Tests

A single function or utility, no DOM involved at all — e.g. testing that formatCurrency(1050) returns "$10.50".

2. Component Tests

Rendering one component in isolation, simulating interaction, asserting on what appears — this course's primary focus, starting Chapter 3.

3. Integration Tests

Multiple pieces working together — a form, its submit handler, and a list that updates in response, all exercised in one test.

4. End-to-End (E2E) Tests

A real (or real-like) browser driving a full user journey — login, add an item, checkout. Tools: Playwright, Cypress — explicitly out of scope for this course.

This Course's Toolchain

Chapter 2 introduces Jest and Vitest as the test runners underneath everything. Chapters 3–5 build up React Testing Library, the tool this course spends the most time on, for component-level testing. Chapter 6 covers mocking dependencies with MSW (Mock Service Worker). Chapter 7 steps back to compare Vue Test Utils, Angular's TestBed, and Svelte Testing Library — since this site already has complete courses for all three frameworks.

The Pyramid Isn't a Strict Law
Kent C. Dodds — the creator of Testing Library, this course's central tool — has argued for a different shape entirely: the "testing trophy," which weights component/integration tests more heavily than pure unit tests, precisely because modern component-testing tools have made them cheap and highly confidence-inspiring. The pyramid is a useful starting mental model, not a rule this course enforces rigidly.
The #1 Beginner Mistake: Testing Implementation, Not Behavior
Asserting that a component's internal state variable holds a specific value, or that a specific CSS class was applied, tests how the component happens to be built right now — not what a real user actually experiences. These tests break constantly during harmless refactors, even when the app still works perfectly. Chapter 3's entire philosophy exists to fix this exact habit before it forms.

Coding Challenges

Challenge 1

For each of the following, classify it as a unit, component, integration, or E2E test, and explain your reasoning: (a) testing a validateEmail(string) function, (b) testing that a Button component renders its label text, (c) testing a full checkout flow across three pages in a real browser.

📄 View solution
Challenge 2

Write a short paragraph explaining why a test that asserts wrapper.find('.is-active').length === 1 (checking a CSS class directly) is more fragile than a test that asserts the user can see text confirming an item is selected.

📄 View solution
Challenge 3

Explain, in your own words, the trade-off the testing pyramid describes — specifically, why a team wouldn't just write nothing but E2E tests, given that they're the most realistic.

📄 View solution

Chapter 1 Quick Reference

  • Unit test — isolated logic, no DOM, fastest and most numerous
  • Component test — one component rendered and interacted with in isolation (this course's main focus)
  • Integration test — multiple components/pieces exercised together
  • E2E test — a real browser, a full user journey, slowest and fewest (out of scope here — Playwright/Cypress territory)
  • The testing pyramid trades realism for speed as you go up — no single layer is "the right one" on its own
  • The "testing trophy" (Kent C. Dodds) weights component/integration tests more heavily — a legitimate alternative shape, not a contradiction
  • Test behavior a user can observe, not internal implementation details — the habit Chapter 3 builds on directly
  • Next chapter: Jest & Vitest Fundamentals — test runner basics, assertions, and setup/teardown