How to Get Up and Running With Vitest

Vitest, the unit test framework powered by Vite shares many similarities with Jest. On the other hand, it offers much more and improves on it. Vitest is built on top of the Jest API, so if you already know how to work with Jest, you will know how to work with Vitest too.

This not only makes the learning curve very shallow but also helps ease the migration process in case you would like to switch from Jest to Vitest. But why Vitest in the first place? Let's take a look at some of the features of Vitest to see what it has to offer, then we will see how you can get up and running with Vitest.


Features of Vitest

First and foremost, Vitest is compatible with Jest, which means most of your existing unit tests will work with Vitest too. It uses the same API meaning you don't have to learn new ways of writing unit tests.

Apart from the similarity it shares with the Jest API, it comes with a handful of improvements on top of Jest which could make it a better choice:


Writing Your First Unit Tests Using Vitest

To get up and running with Vitest, you first need to have a Vite project. In case you already have one, you can jump to the next section.Β In case you don't have one, you can create a new one using the following command:

npm create vite .

This will initiate a new Vite project in the current directory. You also have the option to choose the following frameworks when bootstrapping Vite:

> vanilla
- vue
- react
- preact
- lit
- svelte

In this tutorial, we are going to go with a vanilla project. During the setup, you can also choose to set up TypeScript along with your Vite project. After your project is bootstrapped, don't forget to run npm i to install all dependencies.

Installing and using Vitest

Once you have a Vite project ready, you will also need to install Vitest as a dev dependency.

npm i --save-dev vitest

Notice that Vitest is still under version 1.x. This means breaking changes might be expected.

Now that we have all the required dependencies installed, it's time to create a test file to start writing some unit test cases. Create a new test file somewhere in your project's folder and add the following:

import sum from './sum'
import { describe, it, expect } from 'vitest'

describe('sum', () => {
    it('Should sum two numbers together', () => {
        expect(sum(3, 3)).toBe(6)
    })
})
vitest.test.tsTesting a sum function with Vitest
Copied to clipboard!

The very first thing you may notice is that in Vitest, we need to import the different building blocks of a unit test. Other than that, the syntax is more or less the same as Jest.

To run the test, open your package.json file and create a new test command in your scripts object.

{
    "scripts": {
        ...
        "test": "vitest"
    }
}
package.jsonCreate a new command in your package.json to run Vitest
Copied to clipboard!

Now you can call npm run test to execute Vitest to run your tests. This will run Vitests in watch mode, meaning you can make some changes to your unit tests, save the file, and Vitest will rerun your test suite.

The good thing? If you have multiple test files (which you will likely have), Vitest will only execute the file that is changed, so no need to wait for all the other tests to pass. To perform a single run without watch mode, you can change your test script to call vitest run.

{
    "scripts": {
        ...
        "test": "vitest run"
    }
}
Use "vitest run" if you want to execute Vitest in your CI
Copied to clipboard!

Apart from the Jest compatible APIs, Vitest also has Chai built-in for assertions, as well as jsdom for DOM mocking. All of this makes it super easy to migrate your test suite from Jest to Vitest.


In-source Testing

Another great feature of Vitest is in-source testing. In-source testing lets you write your test cases right next to your functions. Let's see how the above example can be translated to in-source testing.

First, you will need to move your unit test underneath your exported function, and wrap it in the following if statement:

import { describe, it, expect } from 'vitest'

export const sum = (a: number, b: number): number => a + b

if (import.meta.vitest) {
    describe('sum', () => {
        it('Should sum two numbers together', () => {
            expect(sum(2, 2)).toBe(4)
        })
    })
}
sum.tsIn-source testing in Vitest
Copied to clipboard!

This check will tell Vite to only run the code if we are executing Vitest. So the part inside the if statement will only be executed if we are running the code from the unit test suite. Now using this approach we will run into three problems:

Luckily, all three of them can be resolved relatively easily. To let Vitest find the test, we need to modify our vite.config file. Inside your vite.config, add the following to your defineConfig call.

import { defineConfig } from 'vitest/config'

export default defineConfig({
    test: {
        includeSource: ['**/*.ts']
    }
})
vite.config.tsAdd includeSource to your vite.config file
Copied to clipboard!

This will tell Vitest to look for tests in files ending with .ts. By default, it will only look for tests in files with a .test.extension or .spec.extension ending. To ensure that the test code is not included in the final bundle, we can extend the config with the following lines:

import { defineConfig } from 'vitest/config'

export default defineConfig({
+   define: {
+       'import.meta.vitest': 'undefined'
+   },
    test: {
        includeSource: ['**/*.ts']
    }
})
vite.config.ts
Copied to clipboard!

This will ensure that import.meta.vitest will always be skipped for production builds. Last but not least, to fix type errors related to import.meta.vitest, we need to modify tsconfig.json with an extended type.

"types": [
    "vitest/importMeta"
]
tsconfig.jsonAdd the type to your tsconfig file to avoid type errors with Vitest during in-source testing
Copied to clipboard!

Test Coverage Reports Using Vitest

Vitest supports generating test coverage out of the box. It requires c8 as a dependency, so in case you don't have it installed, run npm i --save-dev c8. Vitest will also prompt you to install it during the first coverage run. To create a coverage report, run vitest --coverage. This will generate a report into your terminal.

Vitest coverage report shown inside the terminal
Coverage report shown inside the terminal

In case you want to work with a coverage report represented by HTML, you can add the following config to your vite.config file.

import { defineConfig } from 'vitest/config'

export default defineConfig({
    test: {
        coverage: {
            reporter: ['text', 'html']
        }
    }
})
Copied to clipboard!

This will generate a coverage folder at the root of your project, where you can find an index.html report file for your code coverage, that is generated using Istanbul.

100 JavaScript Project Ideas

Summary

In summary, Vitest provides various improvements on top of Jest. Its similar API to Jest makes it very easy to migrate your unit tests. Its single configuration file lets you configure both your app and your unit test suite from one place. Its implementation lets you execute your test suite faster compared to Jest.

Have you already worked with Vitest before? Let us know your thoughts on it in the comments below! Want to learn more about unit testing? Check out our tutorials below on how to achieve various test scenarios in Jest.Β Thank you for reading through, happy testing!

100 JavaScript Project Ideas
Remove ads
Remove ads

πŸ“š Get access to exclusive content

Want to get access to exclusive content? Support webtips with the price of a coffee to get access to tips, checklists, cheatsheets, and much more. β˜•

Get access Support us
Remove ads Read more on
Remove ads
Remove ads
πŸŽ‰ Thank you for subscribing to our newsletter. x