DEV Community

Abhishek V
Abhishek V

Posted on • Edited on

Vitest - Blazing fast component testing for React

Source Code available at Github

In this article

Introduction

Unit testing is a crucial practice in software development that involves evaluating individual units of code to ensure they function correctly. It forms an integral part of Test-Driven Development (TDD), a methodical approach that emphasizes continuous testing and revision during the development process. In this article, we will explore how to utilize Vitest, a modern testing framework powered by Vite, to rigorously test React components. Our primary goal is to validate the functionality of our code and detect potential bugs early in the development cycle.

Why Vitest?

Vitest stands out as a cutting-edge testing framework, benefiting from the speed and efficiency of the Vite build tool. It offers a zero-config setup, simplifying the testing process for React components.

To follow along with this tutorial, you can clone the Starter Project and switch to the before-vitest branch using the following commands:



git clone https://github.com/Abhi0498-Blogs/vitest-react.git
cd vitest-react
git checkout before-vitest
npm i
npm run dev


Enter fullscreen mode Exit fullscreen mode

This will initiate the development server, accessible at http://localhost:5173.

Begin by installing Vitest and @testing-library/react:



yarn add -D vitest @testing-library/react


Enter fullscreen mode Exit fullscreen mode

Now, let's configure our vite.config.js file as follows:



// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: "jsdom",
  },
});


Enter fullscreen mode Exit fullscreen mode

In this configuration:

  • globals makes all variables available in test files.
  • environment sets the environment to jsdom, which is the default environment for Vitest.

To manage testing, update your package.json scripts:



// package.json
{
  "scripts": {
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:ui": "vitest --ui",
    "test:coverage": "vitest --coverage"
  }
}


Enter fullscreen mode Exit fullscreen mode

These scripts facilitate various testing scenarios:

  • test: Run all tests.
  • test:watch: Execute tests in watch mode.
  • test:ui: Launch the Vitest UI.
  • test:coverage: Generate a coverage report.

Setting up the Test Environment

Create a __tests__ folder within the src directory to house your tests:



mkdir src/__tests__


Enter fullscreen mode Exit fullscreen mode

Now, let's take a closer look at the src/components/buttons/ folder, which contains four components: IncreaseButton, DecreaseButton, IncreaseBy10Button, and DecreaseBy10Button. We'll begin by testing the IncreaseButton component.

Create a new file called IncreaseButton.test.jsx within the __tests__ folder:



touch src/__tests__/IncreaseButton.test.jsx


Enter fullscreen mode Exit fullscreen mode

Now, let's start writing our first test:



// src/__tests__/IncreaseButton.test.jsx
import { describe, expect, test } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import IncreaseButton from "../components/buttons/increase";
import { useState } from "react";

describe("IncreaseButton", () => {
  test("renders", () => {
    render(<IncreaseButton />);
    expect(screen.getByText("Increase")).toBeDefined();
  });
});


Enter fullscreen mode Exit fullscreen mode

In the code above:

  • describe is used to group tests together.
  • test is used to define a test case.
  • render renders the component.
  • screen provides access to DOM elements.
  • expect is used for assertions.

By executing this test, we ensure that the component renders without errors. If the "Increase" text is found in the DOM, the test passes; otherwise, it fails.

Now, let's run the test:



npm run test


Enter fullscreen mode Exit fullscreen mode

If the test succeeds, you'll see a result similar to this:

Image description

This represents a test case—a set of conditions used to validate the system under test (SUT). Additionally, it highlights the importance of testing, as any future changes to the component that alter the text "Increase" will trigger a test failure.

Testing Component Behavior

Let's write a test to verify that the count increases when the button is clicked. To achieve this, we'll add another test within the describe block:



// src/__tests__/IncreaseButton.test.jsx
test("should increase count by 1", () => {
  // Arrange
  const ButtonWithCount = () => {
    const [count, setCount] = useState(0);
    return (
      <>
        <div data-testid="count">{count}</div>

        <IncreaseButton setCount={setCount} />
      </>
    );
  };

  // Act
  render(<ButtonWithCount />);

  const count = screen.getByTestId("count");
  const button = screen.getByText("Increase");

  fireEvent.click(button);

  // Assert
  expect(count.textContent).toBe("1");
});


Enter fullscreen mode Exit fullscreen mode

In this test:

  • We create a component called ButtonWithCount, which includes a count state and the IncreaseButton component.
  • The render function renders ButtonWithCount.
  • fireEvent is used to simulate a click on the button.
  • expect is employed to assert that the count has increased to 1.

Now, let's run this test using the Vitest UI:



npm run test:ui


Enter fullscreen mode Exit fullscreen mode

You'll see the Vitest UI, where you can execute your tests:

Image description

Running tests in the UI offers a visual and interactive approach to testing your components.

Conclusion

In this tutorial, we've covered the fundamentals of unit testing using Vitest and how to test React components effectively. Remember that this is just the beginning, and there are more components in the src/components/buttons/ folder that you can test to gain a deeper understanding of Vitest.

By writing tests for your code, you not only ensure its reliability but also catch potential issues early in the development process. Embrace testing as a vital practice in your software development journey.

Happy Coding! 🎉

Top comments (3)

Collapse
 
monaye profile image
Monaye Win

Great article. Didn't now about ui. Really cool stuff.
I created React/Typescript/Vitest starter template based on this, if anyone interested. Welcome any improvement too -
github.com/monaye/vite-vitest-reac...

Collapse
 
ginna_baker_c818bd65e9e28 profile image
ginna baker

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@vitejs/plugin-react-swc'

^^ This package needs to be included when the dev deps are installed at the beginning.

Collapse
 
wiseinvoker profile image
Nick L.

This article is very helpful. Thank you for sharing.