Testing ensures that React applications work correctly and continue to work after changes are made.
Without testing:
With testing:
Popular testing tools include:
Note: Throughout this course, we will primarily focus on Vitest and React Testing Library, as these are the most common testing tools used in modern React applications.
Testing is the process of verifying that code behaves as expected.
Example:
User Clicks Button
│
▼
Counter Increases
A test automatically confirms that this behavior works correctly.
Instead of manually checking your application every time you make changes, automated tests verify that existing functionality still works.
Testing provides many benefits:
As projects grow, testing becomes increasingly important because small changes can accidentally break existing features.
React applications are commonly tested at three different levels.
Unit testing verifies a small piece of code independently.
Examples:
Example:
add()
or
<Button />
Each unit is tested in isolation.
Integration testing verifies that multiple pieces of an application work together.
Example:
Form
+
Validation
+
API Call
Instead of testing each part individually, the entire workflow is tested.
End-to-End testing simulates a real user using the application.
Example:
Login
│
▼
Dashboard
│
▼
Logout
The entire application is tested from start to finish.
Throughout this course we will primarily use Vitest.
Vitest is a modern testing framework built specifically for Vite applications.
It is often considered the modern alternative to Jest.
Vitest provides:
Since many React projects today use Vite, Vitest has become a popular testing solution.
npm install -D vitest
Suppose we have a function:
function add(a, b) {
return a + b;
}
Create a test:
import {
test,
expect
} from "vitest";
test(
"adds numbers",
() => {
expect(
add(2, 3)
).toBe(5);
}
);
If the function returns 5, the test passes.
Otherwise, it fails.
A typical Vitest test contains three parts:
Test Name
│
▼
Expected Value
│
▼
Assertion
Example:
test(
"adds numbers",
() => {
expect(
add(2, 3)
).toBe(5);
}
);
"adds numbers" describes the test.expect() receives the actual result.toBe() checks whether it matches the expected value.Assertions verify expected behavior.
expect(5).toBe(5);
expect(true)
.toBeTruthy();
expect(false)
.toBeFalsy();
Jest is one of the most popular JavaScript testing frameworks.
Historically, most React projects used:
Jest
+
React Testing Library
Today, many Vite-based projects prefer:
Vitest
+
React Testing Library
because Vitest integrates directly with Vite and generally provides faster test execution.
React Testing Library (RTL) is the most popular library for testing React components.
Its philosophy is simple:
Test your application the way users use it.
Instead of testing implementation details, focus on user interactions and visible behavior.
npm install -D @testing-library/react
function Button() {
return (
<button>
Login
</button>
);
}
import {
render,
screen
}
from "@testing-library/react";
test(
"renders button",
() => {
render(
<Button />
);
expect(
screen.getByText(
"Login"
)
).toBeInTheDocument();
}
);
The test verifies that the Login button appears on the page.
React Testing Library provides:
render()
This renders a React component into a virtual testing environment.
Example:
render(
<Button />
);
The screen object helps locate elements.
Examples:
screen.getByText("Login");
screen.getByRole("button");
screen.getByPlaceholderText("Email");
These methods simulate how users find elements on the page.
Applications become useful only when users interact with them.
React Testing Library uses user-event to simulate those interactions.
npm install -D @testing-library/user-event
import userEvent
from
"@testing-library/user-event";
await userEvent.click(
button
);
This behaves similarly to an actual user clicking a button.
render(
<Counter />
);
await userEvent.click(
screen.getByRole(
"button"
)
);
expect(
screen.getByText("1")
).toBeInTheDocument();
The test performs these steps:
Render Counter
│
▼
Click Button
│
▼
Verify Count = 1
Good candidates for testing include:
Focus on user-visible behavior rather than implementation details.
Cypress is an End-to-End (E2E) testing framework.
Instead of testing a single component, Cypress tests complete user workflows.
Example:
Open Website
│
▼
Login
│
▼
Dashboard
│
▼
Logout
npm install -D cypress
describe(
"Login",
() => {
it(
"logs in user",
() => {
cy.visit(
"/login"
);
}
);
}
);
Cypress provides:
It allows developers to watch tests execute inside a real browser.
Playwright is a modern End-to-End testing framework developed by Microsoft.
It has become increasingly popular for testing modern web applications.
Playwright provides:
Unlike many older tools, it can test multiple browsers using the same code.
npm init playwright
import {
test,
expect
}
from
"@playwright/test";
test(
"homepage",
async ({
page
}) => {
await page.goto(
"/"
);
}
);
Playwright supports:
This makes it suitable for large production applications.
| Feature | Cypress | Playwright |
|---|---|---|
| Learning Curve | Easy | Easy |
| Browser Support | Good | Excellent |
| Performance | Good | Excellent |
| Mobile Testing | Limited | Excellent |
| Popularity | High | Very High |
Today many React applications use:
Vitest
+
React Testing Library
+
Playwright
Each tool has a specific responsibility.
A common testing strategy is the Testing Pyramid.
E2E Tests
▲
│
Integration Tests
▲
│
Unit Tests
Most tests should be Unit Tests because they are:
Only a small number should be End-to-End tests.
You should be familiar with:
because they are widely used in the industry.
However, throughout this course we will primarily focus on:
Vitest
+
React Testing Library
This combination is ideal for testing React components and application logic.
Good:
Avoid testing internal implementation whenever possible.
Each test should verify one behavior.
Good:
✓ Button renders
✓ Button increments counter
✓ Form submits
Avoid combining many unrelated behaviors into a single test.
Good:
"renders login button"
"increments counter when clicked"
Bad:
"test1"
Instead of directly calling component methods, simulate real user interactions.
await userEvent.click(
button
);
This better reflects actual application behavior.
Prioritize testing:
These areas are more likely to introduce bugs.
| Tool | Purpose |
|---|---|
| Vitest | Modern Test Runner |
| Jest | Traditional Test Runner |
| React Testing Library | React Component Testing |
| Cypress | End-to-End Testing |
| Playwright | Modern E2E Testing |
Several testing tools exist for React applications:
For modern React development, the most practical testing stack is:
React
│
▼
Vitest
│
▼
React Testing Library
while Playwright is increasingly becoming the preferred choice for end-to-end testing.
A typical testing workflow looks like:
React Component
│
▼
Vitest
│
▼
React Testing Library
│
▼
Verify User Behavior
This approach provides fast, reliable, and maintainable tests, giving developers confidence that their React applications continue to work correctly as they evolve.