← Back to React Course | Chapter 12: Testing React Applications | Lesson 1 of 9

Introduction to Testing React Apps

Testing React apps is like a dress rehearsal before a play — you check that everything works correctly on stage before a real audience ever sees it.

Why Test React Components

As an app grows, manually clicking through every feature after each change becomes slow and error-prone. Automated tests let you verify a component still behaves correctly in seconds, catching regressions (things that used to work but broke) before they reach real users.

Note: Start by testing your most critical user flows (like checkout or login) — you don't need 100% coverage to get real value from testing.

Warning: Tests run in a Node.js environment via Jest/Vitest, not in an actual browser — they can't run in this CDN-only preview sandbox.

Example: Why Test React Components

markup
// Run in your local React project (npm install required)
// Button.test.jsx
import { render, screen } from '@testing-library/react';
import Button from './Button';

test('renders button text', () => {
  render(<Button>Click me</Button>);
  expect(screen.getByText('Click me')).toBeInTheDocument();
});

⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.

Testing Behavior, Not Implementation

Good React tests check what a USER would see or do — visible text, clickable buttons, form submissions — rather than internal details like a component's specific state variable names. This makes tests more resilient to refactoring, since they don't break just because you renamed an internal variable.

Note: If a test would need to change just because you refactored a component's internals (without changing its behavior), that's a sign the test is too implementation-focused.

Warning: Testing internal state directly (rather than through the rendered output) couples your tests tightly to implementation details that could change for unrelated reasons.

Example: Testing Behavior, Not Implementation

markup
// Run in your local React project (npm install required)
// Good: tests what the user sees
test('shows error message on invalid email', () => {
  render(<SignupForm />);
  fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'bad' } });
  fireEvent.click(screen.getByText('Submit'));
  expect(screen.getByText('Invalid email')).toBeInTheDocument();
});

The Testing Pyramid: Unit, Integration, E2E

Tests generally fall into three levels: unit tests check one small piece in isolation, integration tests check several pieces working together, and end-to-end (E2E) tests simulate a full real user flow through the entire app. Most teams write many unit tests, fewer integration tests, and only a handful of E2E tests.

Note: This shape (many unit, some integration, few E2E) balances speed (unit tests run fast) against realism (E2E tests catch more real-world issues but run slower).

Warning: Relying only on E2E tests makes your test suite slow and brittle; relying only on unit tests can miss bugs in how pieces interact together.

Example: The Testing Pyramid: Unit, Integration, E2E

markup
// Run in your local React project (npm install required)
// Unit: tests one function/component in isolation
test('formatPrice formats correctly', () => { expect(formatPrice(5)).toBe('$5.00'); });

// Integration: tests a form + validation working together
// (see the previous section's example)

// E2E: tests a full flow (often with Cypress/Playwright)
// cy.visit('/signup'); cy.get('#email').type('[email protected]'); cy.get('button').click();
Common Mistakes
  1. Testing implementation details (internal state variable names) instead of what the user actually sees and does.
  2. Writing tests only for the happy path and never checking error/edge cases.
  3. Not running tests regularly, letting broken tests pile up unnoticed.
Chapter Summary
  • Testing React apps typically involves a test runner (like Jest or Vitest) plus React Testing Library for rendering components.
  • Good tests focus on user-visible behavior, not internal implementation details.
  • Common test types include unit tests (one function/component), integration tests (several working together), and end-to-end tests (a full user flow).
  • Tests catch regressions early, before they reach real users.
Browser Support

Requires npm install (Jest/Vitest + @testing-library/react) — tests run in Node, not this browser sandbox.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.