Why I’m moving from Jest to Vitest
Tags: javascript, vite, webdev
Published: 2022-04-07 13:21:38

I've always reached out to [Jest](https://jestjs.io/) for any JavaScript testing, but I think it's time to rethink that. I just discovered [Vitest](https://vitest.dev/), and thought I'd try it out in one of my projects. It feels like a test runner for 2022 - it covers everything Jest does, plus a few extras that just make it a great alternative.

---

![Section 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/998qgqm1q2llkv661l0h.png)

## It has a UI!
Vitest comes with a UI that runs in the browser. It can show code, and even print out `console.log()` calls!

This might seem excessive for those who prefer the command line, but it makes for a lot of convenient things like drilling down to specific tests.

![](https://i.imgur.com/PKpfZ94.jpg)

<figcaption>☝Run `vitest --ui` to run the test UI in the browser.</figcaption>

---

![Section 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njny1r5hen7rbppx9hso.png)

## ES modules, TypeScript and more
Vitest supports modern features like <mark>ES modules, TypeScript, JSX, PostCSS, async-await and more</mark>—all without the need for complex configuration. ([docs](https://vitest.dev/guide/features.html#common-web-idioms-out-of-the-box))

In contrast, getting these things to work with Jest has often been frustrating. The most practical way is to [use Babel](https://jestjs.io/docs/getting-started#using-babel) alongside Jest to compile JavaScript, and use workarounds to [make Jest ignore CSS files](https://jestjs.io/docs/webpack#mocking-css-modules).

With Vitest, it seems these things just work.

```javascript
import 'react' from React
import 'react-dom' from ReactDOM

it('works', () => {
  ReactDOM.render(<div>hello!</div>, document.body)
  expect(document.body.innerText).toBe('hello!')
})
```

<figcaption>☝ A test like this will require a Babel pipeline in Jest. In Vitest, it should work with the default config.</figcaption>


---

![Section 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jp9p27qxbz9lw3nafoa0.png)

## The API is Jest-compatible (mostly)
Vitest makes migrating from Jest as easy as possible. <mark>It supports Jest assertions by default.</mark>

That was exciting enough, but I was surprised to see that the Jest interop goes even further. Special functions like `jest.useFakeTimers()` have equivalents Vitest as `vi.useFakeTimers()`.

```js
/* Vitest */
const spy = vi.spyOn(obj, 'getApples').mockImplementation(() => apples)

/* Jest */
const spy = jest.spyOn(obj, 'getApples').mockImplementation(() => apples)
```

<figcaption>☝ Just change `jest` to `vi`.</figcaption>

---

![Section 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4uv5lk77615zhfwxeay1.png)

## Jsdom is optional
Vitest also supports browser emulation via Jsdom… and there’s more.

Unlike Jest which always runs with Jsdom by default, Jsdom can be turned off in Vitest. In fact, there are options of what environment to emulate. As of v0.8, Vitest supports `node`, `jsdom` and `happy-dom`.

```javascript
/**
 * @vitest-environment jsdom
 */
 ```

<figcaption>☝ Adding this to the top of a test file enables Jsdom.</figcaption>

---

![Section 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v73gusel2p8hj9yrj9u3.png)

## No global pollution
Unlike Jest which automatically drops things into the global context (eg, `expect()`, `describe()`, etc), Vitest requires importing them in every test file. While this may be a bit more typing, I think it’s more explicit and follows principle of least surprise.

It’s also possible to have them globalised automatically to make migration from Jest easier. ([docs](https://vitest.dev/config/#globals))

```js
import { expect, test } from 'vitest'

test("My test", () => {
  expect(2 + 2).toBe(4)
})
```

<figcaption>☝ The functions `expect` and `test` are explicitly imported before use.</figcaption>

---

![Section 6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9waw39ra4mfg5lu7xvci.png)

## Parallel tests work great
Vitest can run tests in parallel—and the feature is stable!

While Jest has `test.concurrent`, it’s been considered as “experimental” for as long as Jest has been around. Vitest’s counterpart of [`test.concurrent`](https://vitest.dev/api/#test-concurrent) seems to be considered stable.

Vitest has multi-threaded support built in and is enabled by default. ([docs](https://vitest.dev/guide/features.html#threads))

```javascript
/*
 * Vitest will attempt to run these tests
 * in parallel:
 */

test.concurrent('concurrent test 1', async() => {
  /* ... */

})
test.concurrent('concurrent test 2', async() => {
  /* ... */
})
```

---

![Section 7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2ibk6i7lxfbo0cg4rad.png)

## Thanks for reading!

Thanks for checking out my post! I'm a web developer who loves open source and JavaScript. If you liked this post, consider [following me on Dev.to (@rstacruz)](https://dev.to/rstacruz) or [Twitter (@rstacruz)](https://twitter.com/rstacruz)!

- [Vitest](https://vitest.dev/)