Background image

Testing

Vitest vs. Jest

Nolan Sullivan

Nolan Sullivan

September 30, 2024

Featured blog post image

Effective testing frameworks are essential in building reliable JavaScript applications, helping you minimize bugs and catch them early to keep your customers happy. Choosing the right testing framework saves hours of configuration hassles and improves developer experience.

This post compares Jest (opens in a new tab) and Vitest (opens in a new tab), popular JavaScript testing frameworks that support unit testing, integration testing, and snapshot testing (opens in a new tab).

Jest — created by the Facebook team, is the most widely used JavaScript testing framework.

Vitest — a fast-growing new testing framework. Originally built for Vite (opens in a new tab), the popular development server and JavaScript bundler, Vitest can now be used with any JavaScript project, not just those using Vite.

Which JavaScript testing framework is right for you?

We think Vitest is best, unless you’re using a framework or library that has better Jest support, such as React Native. The table below compares some features of the two testing frameworks. If you’re starting a new project, use Vitest. With ES module, TypeScript, JSX, and PostCSS support out of the box, Vitest is the right choice for almost every modern JavaScript app.

JestVitest
Battle tested by large companies
ES module support✅*
TypeScript support✅+
Browser UI✅*
Type testing✅*
Benchmarking
In-source testing
Browser mode✅*
Snapshot testing
Interactive snapshot testing
Code coverage
Concurrent testing✅*
Sharding support
Multi-project runner
Mocking

* Experimental
+ Using Babel

At Speakeasy, we’ve tried both Jest and Vitest, and ultimately chose Vitest – even without Vite in our setup.

We decided to document our experience and dive deeper into both Vitest and Jest, comparing the two testing frameworks in terms of their features, performance, and developer experience to further help you decide which is best for your use case. We’ll also share our experience of migrating from Jest to Vitest for our TypeScript SDK and how we’re using Vitest for our new automated API testing feature, which is currently in beta, for Speakeasy-created SDKs.

Jest’s beginnings: From Facebook to open source

Back in 2011, no JavaScript testing framework existed that met the Facebook (now Meta) team’s testing needs, so they built Jest. Jest was open-sourced in 2014, shortly after React was open-sourced, and as React rapidly gained in popularity, so did Jest.

Popular React project starter Create React App (opens in a new tab) integrated Jest as its default testing framework in 2016 and Jest soon became the go-to testing tool for React developers. When Next.js, the most popular React framework, included built-in Jest configuration in version 12, Jest’s dominance in the React ecosystem was secured.

Ownership of Jest was transferred to the OpenJS Foundation (opens in a new tab) in 2022 and the framework is currently maintained by a core group of contributors external to Meta.

Jest features

Jest’s popularity is in part thanks to the extensive Jest API that handles a variety of testing needs, including snapshots, mocking, and code coverage, making it suitable for most unit testing situations. Jest works with Node.js and frontend frameworks like React, Angular, and Vue, and can be used with TypeScript using Babel or the ts-jest library to transpile TypeScript to JavaScript.

Consider the following example snapshot test:

link.test.js.snap
test("Checkout link renders correctly", () => {
const tree = renderer
.create(<Link page="http://www.instagram.com">Go to checkout</Link>)
.toJSON();
expect(tree).toMatchSnapshot();
});

The test (opens in a new tab) method runs a test. The Jest expect API (opens in a new tab) provides modifier and matcher (assertion) methods that simplify checking whether a value is what you expect it to be. Among the matcher methods available are:

  • toBe()
  • toHaveProperty()
  • toMatchSnapshot()

Jest’s extensive set of modifiers and matchers makes error messages more detailed, helping you pinpoint why a test fails. The jest-extended (opens in a new tab) library, maintained by the Jest community, provides additional matchers to expand testing functionality.

You can use Jest’s mock functions (opens in a new tab) to mock objects, function calls, and even npm modules for faster testing without relying on external systems. This is especially useful for avoiding expensive function calls like calling a credit card charging API in the checkout process of an app.

To run code before and after tests run, Jest provides handy setup and teardown functions (opens in a new tab): beforeEach, afterEach, beforeAll, and afterAll.

cityDb.test.js
beforeAll(() => {
return initializeCityDatabase();
});
afterAll(() => {
return clearCityDatabase();
});
cityDb.test.js
beforeEach(() => {
initializeCityDatabase();
});
afterEach(() => {
clearCityDatabase();
});
test("city database has Vienna", () => {
expect(isCity("Vienna")).toBeTruthy();
});
test("city database has San Juan", () => {
expect(isCity("San Juan")).toBeTruthy();
});

When running tests, you can add the --watch flag to only run tests related to changed files.

jest --watch

While Vitest doesn’t have Jest’s Interactive Snapshot Mode (opens in a new tab), which enables you to update failed snapshots interactively in watch mode, this feature has been added to Vitest’s TODO list (opens in a new tab).

Jest also has a multi-project runner for running tests across multiple projects, each with their own setup and configuration, using a single instance of Jest.

Getting started with Jest

To set up a basic test, install Jest as a development dependency:

npm install --save-dev jest

Create a test file with .test in its name, for example, sum.test.js:

sum.test.js
const sum = require("./sum");
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});

This code imports a sum function that adds two numbers and then checks that 1 and 2 have been correctly added.

Add the following script to your package.json file:

package.json
{
"scripts": {
"test": "jest"
}
}

Run the test using the following command:

npm run test

Jest finds the test files and runs them. Jest will print the following message in your terminal if the test passes:

PASS ./sum.test.js
adds 1 + 2 to equal 3 (5ms)

The origin of Vitest: The need for a Vite-native test runner

The introduction of in-browser ES modules support led to the creation of the popular JavaScript bundler and development server Vite, which uses ES modules to simplify and speed up bundling during development. While it’s possible to use Jest with Vite, this approach creates separate pipelines for testing and development. Among other factors, Jest requires separate configuration to transpile ES modules to CommonJS using Babel. A test runner that supports ES modules would integrate better with Vite and simplify testing. Enter Vitest.

Developed by core Vite team member, Anthony Fu, Vitest is built on top of Vite, but you can use it in projects that don’t use Vite.

Vite’s rise in popularity can be attributed to its simplicity and performance. Unlike traditional JavaScript bundlers that can be slow when running development servers for large projects, the Vite development server loads fast, as no bundling is required. Instead, Vite transforms and serves source code as ES modules to the browser on demand, functionality that allows for fast Hot Module Replacement (HMR) - the updating of modules while an app is running without a full reload - even for large applications.

In development, the main advantages of using Vitest with Vite are their performance during development, ease of integration, and shared configuration. Vitest’s growing adoption is partly driven by the widespread success of Vite.

Vitest features

Vitest has built-in ES module, TypeScript, JSX, and PostCSS support and many of the same features as Jest, like the expect API, snapshots, and code coverage. Vitest’s Jest-compatible API makes migrating from Jest easy. Take a look at the differences between the frameworks in the migrating from Jest guide (opens in a new tab) in the Vitest docs.

In contrast to Jest, Vitest uses watch mode by default for a better developer experience. Vitest searches the ES module graph and only reruns affected tests when you modify your source code, similar to how Vite’s HMR works in the browser. This makes test reruns fast - so fast that Vitest adds a delay before displaying test results in the terminal so that developers can see that the tests were rerun.

Vitest supports Happy DOM (opens in a new tab) and jsdom (opens in a new tab) for DOM mocking. While Happy DOM is more performant than jsdom, which is used by Jest, jsdom is a more mature package with a more extensive API that closely emulates the browser environment.

When running tests, Vitest runs a Vite dev server that provides a UI for managing your tests.

To view the UI, install @vitest/ui and pass the --ui flag to the Vitest run command:

vitest --ui

Vitest UI

Take a look at the StackBlitz Vitest Basic Example (opens in a new tab) for a live demo of the Vitest UI. At Speakeasy, we’ve found Vitest’s UI to be a valuable tool for debugging.

Vitest also has Rust-like in-source testing (opens in a new tab) that lets you run tests in your source code:

add.ts
export function add(...args: number[]) {
return args.reduce((a, b) => a + b, 0)
}
// in-source test suites
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest
it('add', () => {
expect(add()).toBe(0)
expect(add(1)).toBe(1)
expect(add(1, 2, 3)).toBe(6)
})
}

While using separate test files is recommended for more complex tests, in-source testing is suitable for unit testing small functions and prototyping, making it especially useful for writing tests for JavaScript libraries.

Vitest’s recent experimental browser mode (opens in a new tab) feature allows you to run tests in the browser, instead of simulating them in Node.js. WebdriverIO (opens in a new tab) is used for running tests, but you can use other providers. You can also browse in headless mode using WebdriverIO or Playwright (opens in a new tab). Vitest developed browser mode to improve test accuracy by using a real browser environment and streamline test workflows, but you may find browser mode slower than using a simulated environment as it needs to launch a browser, handle page rendering, and interact with browser APIs.

Other experimental features include type testing (opens in a new tab) and benchmarking (opens in a new tab).

Getting started with Vitest

The set up and execution of a basic test in Vitest is similar to Jest.

First, install Vitest as a development dependency:

npm install --save-dev vitest

Create a test file with .test or .spec in its name, for example, sum.test.js:

sum.test.js
import { expect, test } from "vitest";
import { sum } from "./sum.js";
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});

This code imports a sum function that adds two numbers and then checks that 1 and 2 have been correctly added.

Compared to Jest, this basic test is a little different. Vitest uses ES module imports, and for the sake of explicitness, it does not provide global APIs like expect and test by default. You can configure Vitest to provide global APIs (opens in a new tab) if you prefer or are migrating from Jest.

Add the following script to your package.json file:

package.json
{
"scripts": {
"test": "vitest"
}
}

Run the test using the following command:

npm run test

Vitest finds the files and runs them, and will print the following message in your terminal if the test passes:

sum.test.js (1)
adds 1 + 2 to equal 3
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 02:15:44
Duration 311ms

Note that Vitest starts in watch mode by default in a development environment.

Choosing between Vitest and Jest

Let’s compare the two testing frameworks in terms of performance, developer experience, community and ecosystem, and their usage with Vite.

Performance

Performance comparisons of Vitest and Jest have delivered conflicting results, as the outcome depends on what you’re testing and how you configure the testing tool. One blog post reports that Jest is faster than Vitest (opens in a new tab) when running all the tests for the author’s blog website. Another comparison (opens in a new tab), which performed 1,256 unit tests on a production web app that uses Vite and Vue, found that Vitest was faster than Jest in most tests. Yet another comparison (opens in a new tab) found Jest to be almost twice as fast as Vitest for testing a production app. Ideally, benchmark your own tests to see which testing tool is faster for your use case, or make a choice based on other factors as the performance differences may not be significant.

Even if your benchmarking finds Jest is faster than Vitest, there are ways to improve Vitest’s performance, as explained in the improving performance guide (opens in a new tab) in the Vitest docs.

For example, you can disable test isolation (opens in a new tab) for projects that don’t rely on side effects and properly clean up their state, which is often the case for projects in a node environment.

In watch mode, Vitest often outperforms Jest when rerunning tests, as it only reruns tests affected by code changes. While Jest also only reruns changed tests in watch mode, it relies on checking uncommitted Git files, which can be less precise, as not all detected changes may be relevant to the tests you’re running.

Developer experience

Both Jest and Vitest have comprehensive, well-organized, and easy-to-search documentation. The Jest docs include guides for specific types of tests such as timer mocks (opens in a new tab) and using Jest with other libraries, databases, web frameworks, and React Native. Vitest’s getting started guide (opens in a new tab) sets it apart. It includes StackBlitz examples that you can use to try Vitest in the browser without setting up a code example yourself. The getting started guide also has example GitHub repos and StackBlitz playgrounds for using Vitest with different web frameworks.

Vitest’s ES module support gives it a significant advantage over Jest, which only offers experimental support for ES modules (opens in a new tab).

Jest uses Babel (opens in a new tab) to transpile JavaScript ES Modules to CommonJS, using the @babel/plugin-transform-modules-commonjs (opens in a new tab) plugin. By default, Babel excludes Node.js modules from transformation, which may be an issue if you use an ES-module-only library (opens in a new tab) like react-markdown (opens in a new tab), in which case you’ll get this commonly seen error message:

SyntaxError: Unexpected token 'export'

To fix this issue, use the transformIgnorePatterns (opens in a new tab) option in your jest.config.js file to specify that the Node module is an ES module package that needs to be transpiled by Babel:

jest.config.js
/** @type {import('jest').Config} */
const config = {
...
"transformIgnorePatterns": [
"node_modules/(?!(react-markdown)/)"
],
};
module.exports = config;

Jest supports TypeScript using Babel, which requires some configuration (opens in a new tab).

Overall, Jest requires some configuration to work with ES modules and TypeScript, which work out of the box with Vitest. Less configuration means happier developers.

RedwoodJS (opens in a new tab), the full-stack, open-source web framework, is in the process of migrating from Jest to Vitest (opens in a new tab). The RedwoodJS team found Vitest much better suited to working with ES modules compared to Jest.

Community and ecosystem

While npm trends (opens in a new tab) show that Jest is downloaded more frequently than Vitest, Vitest usage is rapidly increasing, outpacing Jest in growth.

npm trends graph: Jest vs. Vitest - number of npm downloads over time

GitHub
stars
GitHub
issues
Latest
version
Creation
date
Unpacked
size
Jest44 04128929.7.020115.01 Mb
Vitest12 6342962.1.120211.62 Mb

According to the State of JS 2023 survey (opens in a new tab), Vitest has seen a rapid rise in popularity and positive opinions between 2021 and 2023. By contrast, Jest experienced a rapid rise in popularity and positive opinions between 2016 and 2020, but this momentum slowed between 2021 and 2023, with opinions becoming more mixed. This shift may be due to developers adopting Vitest, which solves one of the main pain points of Jest: ES Module support.

Vite and Vitest claimed many of the top spots in the survey (opens in a new tab), while Jest made an appearance as the second most most-loved library, after Vite.

Of the four most popular JavaScript frontend frameworks and libraries, two use Jest, and two use Vitest. React uses Jest and Angular added experimental Jest support in 2023 with the release of Angular version 16 to modernize its unit testing.

Jest’s popularity and the fact that it’s been around for longer means there are more blog posts and Stack Overflow questions about Jest (opens in a new tab) than Vitest (opens in a new tab), which is useful for figuring out uncommon testing situations and debugging.

Many large companies use Jest, but Vitest is gaining traction in prominent projects (opens in a new tab), including frameworks like Vue and Svelte. Many of the projects using Vitest are built with Vue. This is no surprise, as Evan You, the creator of Vue, also created Vite, and one of Vite’s core team members developed Vitest.

For React developers, Jest’s compatibility with mobile development using React Native and Expo (opens in a new tab) is an important advantage. React Native and Expo testing documentation recommend using Jest, and Expo provides the jest-expo (opens in a new tab) library to simplify testing for Expo and React Native apps.

Vitest, meanwhile, offers support for React Native using the vitest-react-native (opens in a new tab) library, which is developed by a Vitest team member and is a work in progress.

Vitest is under more rapid development than Jest, as can be seen by the number of recent commits to the Vitest GitHub repo (opens in a new tab) compared to the Jest GitHub repo (opens in a new tab).

Recently, Evan You founded VoidZero (opens in a new tab), a company building an open-source, unified development toolchain by bringing together some of the most popular JavaScript toolchain libraries: Vite, Vitest, Rolldown, and Oxc. With $4.6 million in seed funding, VoidZero is likely to accelerate Vitest’s development and boost its popularity.

Using with Vite

If Vite is part of your development toolchain, Vitest’s easy integration with Vite is a compelling advantage, delivering a streamlined setup through shared configuration.

Jest is not fully supported by Vite, but you can get it to work using the vite-jest library, with some limitations (opens in a new tab).

Using Jest with Vite adds complexity as you need to manage testing and building your app as separate processes. However, Angular uses Vite and Jest. The Angular team considered using Vitest but chose Jest because of its widespread adoption among Angular developers and its maturity.

Migrating from Jest to Vitest: Insights from our experience at Speakeasy

Our experience migrating from Jest to Vitest at Speakeasy revealed clear advantages, particularly in speed and ease of setup.

In January, when we rebuilt our TypeScript SDK, switching to Vitest gave us a noticeable runtime boost with zero configuration. Unlike Jest, which required Babel integration, TSJest setup, and multiple dependencies, Vitest worked out of the box, allowing us to drop five dependencies from our project.

Vitest’s compatibility with Jest’s API made the migration smooth, and the intuitive UI provided a browser view with real-time test updates – a significant productivity boost.

Since July, we’ve expanded Vitest’s role in our process by introducing a test generation product, where clients can create Vitest tests for their API SDKs, maintaining minimal dependencies with only Zod and Vitest required.

Vitest has quickly become a strong choice for future-proofing, advancing rapidly with the support of VoidZero and its integration into a modern toolchain that aligns with frameworks like Vue.

Adding automated API testing for Speakeasy-created SDKs using Vitest

When we rebuilt our TypeScript SDK generation – which doesn’t use Vite – we switched from Jest to Vitest and saw a significant improvement in performance. Vitest needed zero configuration – it just worked. Vitest’s Jest-compatible API made the migration straightforward, and we’ve found that Vitest has most of Jest’s features as well as some extras, like its feature-packed, intuitive UI for viewing and interacting with tests.

We are now in the process of expanding our use of Vitest to our customers’ Speakeasy-generated SDKs with an automated API testing feature (opens in a new tab) that generates API tests that will help you make more robust and performant APIs, faster and cheaper. Our own internal SDKs have Vitest tests, which we used to add this feature.

Info Icon

EARLY ACCESS

Speakeasy API test generation is in beta. Join the early access program to give it a try.

Test generation is currently available in Typescript, Python, and Go. Customers can enable test generation in a generated Speakeasy SDK using their OpenAPI doc or using a tests.yaml file. We have plans to further improve testing including:

  • Providing a mock server to run the generated tests against.
  • Adding integration with CI/CD using our GitHub Action.
  • Adding support for more languages.
  • Adding end-to-end testing using the Arazzo specification (opens in a new tab), which allows for more complex testing scenarios.
  • Integration with the Speakeasy web app.

Conclusion: Which testing framework is better?

Vitest’s many experimental features simplify testing and the framework is under active development, a fact that may skew this comparison even more in its favor in the coming years.

While both libraries are easy to get started with, Vitest is easier to set up for modern projects using ES modules and TypeScript, and it’s easier to use with modern npm libraries that are ES modules only.

We think that Vitest is a good successor to Jest. Picking a technology means betting on the future, and we’re betting on Vitest.

CTA background illustrations

Speakeasy Changelog

Subscribe to stay up-to-date on Speakeasy news and feature releases.