Vitest: running JavaScript tests on Vite's own configuration

Vitest runs the tests of a JavaScript project by reusing the Vite configuration: test files, assertions, watch mode and coverage reporting.
3 min read
Believemy logo

A modern project already has a build tool, a module resolver and a file transform. A test runner that asks for all of it a second time starts at a disadvantage.

Vitest made the opposite choice: it plugs into the existing configuration and runs the tests with it.


Definition

Vitest is a JavaScript and TypeScript test runner built on Vite. It discovers test files, runs them, compares expected results against obtained ones and hands back a report. ES module modules work natively, with no conversion step.

JAVASCRIPT
// billing.test.js
import { describe, it, expect } from "vitest";
import { grossTotal } from "./billing.js";

describe("grossTotal", () => {
  it("applies 20% tax by default", () => {
    expect(grossTotal(19)).toBe(22.8);
  });

  it("accepts another rate", () => {
    expect(grossTotal(100, 0.055)).toBe(105.5);
  });
});

A file whose name contains .test. or .spec. is picked up automatically. The npx vitest command runs it and then keeps watching for changes, replaying only what depends on the file that was touched.


The everyday functions

FunctionRole
describeGroups tests that talk about the same subject
it or testDeclares one test and its descriptive sentence
expectOpens an assertion on an obtained value
beforeEachSets up fresh state ahead of every test
viThe object that builds doubles and drives the clock

On the assertion side, toBe compares by identity, toEqual compares content deeply, toThrow expects an Error, and rejects expects a broken promise.


Configuration

A single file is enough to describe the runtime environment and the Code coverage report. It goes at the root of the project, next to the package.json.

JAVASCRIPT
// vitest.config.js
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    environment: "node",
    globals: false,
    coverage: {
      provider: "v8",
      reporter: ["text", "html"],
    },
  },
});
Good to know

Setting environment to jsdom supplies a simulated document and window, which is what allows interface code to be tested without opening a browser.


Frequently asked questions

Question

Vitest or Jest?

The two interfaces are deliberately very close, to the point where a migration often amounts to changing the imports. Vitest wins on a project already served by Vite, since there is then only one configuration to maintain. On an older base tooled with Webpack, the Jest ecosystem remains deeply established.


Question

Should tests run continuously?

While writing, yes: the default mode replays only the tests affected by the modified file, and the feedback loop is measured in tens of milliseconds. In continuous integration you use vitest run, which executes once and then hands back an exit code.


Question

Where should test files live?

Two conventions coexist: next to the file under test, or in a dedicated folder mirroring the tree. The first keeps the test visible and makes it travel with the code it covers. The second keeps production folders clean. What matters is choosing once, for the whole project.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.