Vitest: Blazing Fast Unit Test Framework
A comprehensive introduction to the Vite-powered unit test framework.
If you have heard of Vite, then you have probably heard of Vitest, the fast unit test framework built from it. In this article, let's explore what Vitest is, how to use it and why it can be the next test framework for your apps.
What is Vitest
Before we get into Vitest, let's talk about Vite. Vite is a build tool that allows for faster server starts and updates thanks to its native ESM-based method to serve code on demand.
If you want to read more in detail, feel free to read my Introduction to Vite article here
So Vitest is the unit testing framework built on top of Vite and is an excellent unit test framework with many modern features such as:
Component testing for Vue, React, Svelte, Lit and more
Out-of-the-box TypeScript / JSX support
ESM first, top level await
Multi-threading workers
Filtering, timeouts, concurrent for suite and tests
Jest-compatible Snapshot
Chai built-in for assertions + Jest expect compatible APIs
Designed with a Jest compatible API
Let's get started with a simple example on how to use Vitest in a Vite-powered project.
Example Usage: Writing Unit Tests in Vitest
Step 1: Create a Vite Project
npm create vite .
Note: Vite requires Node.js version 14.18+, 16+.
This will start the process to create a Vite project. You can name your project and choose a template appropriately. For this example, I will be choosing the vanilla
template.
After the project is created, you can install the necessary dependencies by running:
npm install
Now, you should have the following project with this structure:
Finally, to install Vitest, run:
npm install -D vitest
For Non-Vite powered Projects
It is just as easy to setup Vitest in a non-Vite powered projects. Say we have a CRA (Create React App) project and want to use Vitest for testing.
All we need to do is to run:
npm install -D vitest @vitejs/plugin-react
And then add a vite.config.js
in the root folder of the project.
/// <reference types="vitest" />
import { defineConfig } from "vitest/config"
import react from "@vitejs/plugin-react"
export default defineConfig({
plugins: [react()],
server: {
open: true,
},
build: {
outDir: "build",
sourcemap: true,
commonjsOptions: {
include: [],
},
},
optimizeDeps: {
disabled: false,
},
test: {
globals: true,
environment: "jsdom",
setupFiles: "@testing-library/jest-dom",
mockReset: true,
},
})
Step 2: Write some simple tests
Now that our project is set up, let us write some simple tests. Because Vitest has been designed based on Jest, it shares a lot of similarities. One of them is that it can automatically detect your test files as long as you name it in any of the 3 following formats:
A .js file in a folder named
__tests__
A file with a name like
[name].spec.js
A file with a name like
[name].test.js
So let's create a new folder in our example project called tests
and add a basic.test.js
file.
tests/
|- basic.test.js
In the basic.test.js
file, let's create some simple tests.
import { describe, it, assert } from 'vitest'
describe('Math.sqrt() test', () => {
it('SQRT4', () => {
assert.equal(Math.sqrt(4), 2)
})
it('SQRT144', () => {
assert.equal(Math.sqrt(144), 12)
})
it('SQRT2', () => {
assert.equal(Math.sqrt(2), Math.SQRT2)
})
})
If you have worked with other testing libraries such as Jest, Mocha or Jasmine, you should be familiar with the BDD (Behavior Driven Development) pattern. It describes a function, explains what it does and uses test case(s) to assert that it works as intended.
Step 3: Run tests
To run the tests, the command is:
npx vitest
Or you can configure your package.json
to run the command with npm test
:
"scripts": {
"test": "vitest" //add the command to run tests
"coverage": "vitest run --coverage" //command to enable coverage report
}
More Vitest CLI commands can be found at the official documentation.
By default, the tests run in watch mode so if you make any file changes, they will re-run immediately. If the tests are successful, you should see the terminal outputting:
Vitest vs Other Test Frameworks
Vitest is often compared to Jest, another popular test framework. It is because it is built on top of Jest, making it a more modern and improved version. Also, it offers compatibility with most of the Jest API and ecosystem libraries, making it simple to migrate by following their official guide here.
Just like other widely used test frameworks such as Mocha and Jasmine, Vitest also follows a simple describe-it-assert
or describe-it-expect
pattern. The advantage of using Vitest over them is that it is fast to set up and does not require installing a separate assertion library.
The most convenient advantage of using Vitest is that it requires minimal configuration compared to Jest and Babel-based projects. You can define the configuration for your dev, build and test environments as a single pipeline under vite.config.js
.
A simple example would be setting up a Jest and Babel environment for a React app. Often, you would need to install additional packages besides the ones that come with CRA:
babel-jest
@babel/core
@babel/preset-env
@babel/preset-react
@babel/preset-typescript
@types/jest
After that, you would need a jest.config.js
and a babel.config.js
to complete setting up the configuration. With Vitest, you don't have to install all those extra depedencies, all you need is a vite.config.js
or vitest.config.js
file. Even for non-Vite projects, it is a single file to configure.
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'jsdom',
},
});
Learn more about configuration in this documentation.
Below is a summarized comparison of different popular test frameworks with Vitest.
Vitest VS Code Extension
To speed up testing and make debugging easier, there is a VS Code extension for Vitest available in the Marketplace.
This extension can help to:
Filter tests by status
Easy debugging
Inspect console output
Fast test reruns
Learn more about this extension here.
More Features: Test Coverage Report
Let me show a simple example how we can output a test coverage report. First, I create a simple counter function in counter.js
.
export const setCounter = (count) => {
return count+1;
}
Then, I create a test for this function in the counter.test.js
:
import { describe, it, expect } from 'vitest'
import {setCounter} from '../src/counter'
describe("setCounter", ()=>{
it("returns 1",()=>{
expect(setCounter(0)).toBe(1);
})
})
Now if we run vitest run --coverage
, we can see if how much of our code has been tested.
Let's say I add a new function in our counter.js
:
// added another function
export function setupCounter(element) {
element.addEventListener('click', () => {
setCounter(counter++);
element.innerHTML = `count is ${counter}`
})
}
If we run vitest run --coverage
, we can see that not all our code has been tested. This report ensures that most of your project's code is tested.
By default, Vitest uses the v8
package to run coverage reports. You may install it manually with the command:
# UPDATED: now uses v8 instead of c8
npm i -D @vitest/coverage-v8
Update: It now uses v8 for coverage. Screenshots not updated.
Or install it when prompted:
More Features: Component Testing
Another common testing we can do with Vitest is component testing, which verifies the functionality of individual components.
Let's add an App.test.jsx
to a React App. For this example, I'm using a non-Vite project (i.e. basic Create React App template) to show that Vitest works just as fine.
In this test, we want to test only the App
component and here's what our App.test.jsx
will look like:
import { render, screen } from '@testing-library/react';
import {describe, it, expect} from 'vitest';
import App from './App';
describe('App Component Test', ()=>{
it ('renders without crashing', ()=>{
const {container} = render(<App />);
expect(container).toBeInTheDocument();
})
it('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
})
Now we run the tests with npm test
or npx vitest
. And the 2 tests should pass successfully, as shown below.
Conclusion
In this article, we learned about Vitest, a fast and modern unit testing framework powered by Vite. Thanks for reading, I hope it has been a helpful article in getting you started with Vitest. Please refer to the References section below if you would like to read more about Vitest and Vite. Cheers!