A blazing fast unit test framework powered by Vite.
💖 This project is currently in closed beta exclusively for Sponsors.
Become a Sponsor of @patak-js or @antfu to access the source code and issues tracker.
⚠️ DISCLAIMER: Vitest is still in development and not stable yet. It's not recommended to use it in production.
Vitest requires Vite v2.7 and Node v16
- Vite's config, transformers, resolvers, and plugins. Use the same setup from your app!
- Jest Snapshot
- Chai built-in for assertions, with jest-expect compatible APIs.
- Smart watch mode, just like HMR for tests!
- Code coverage
- Sinon built-in for mocking
- JSDOM built-in for DOM and browser API mocking
- Components testing (Vue example, React example)
- Async suite / test, top level await
- ESM friendly
- Out-of-box TypeScript / JSX support
- Suite and Test filtering (skip, only, todo)
- Concurrent Tests
import { it, describe, expect, assert } from 'vitest'
describe('suite name', () => {
it('foo', () => {
expect(1 + 1).toEqual(2)
expect(true).to.be.true
})
it('bar', () => {
assert.equal(Math.sqrt(4), 2)
})
it('snapshot', () => {
expect({ foo: 'bar' }).toMatchSnapshot()
})
})
$ npx vitest
vitest
will read your root vite.config.ts
when it present to match with the plugins and setup as your Vite app. If you want to it to have a different configuration for testing, you could either:
- Create
vitest.config.ts
, which will have the higher priority - Pass
--config
option to CLI, e.g.vitest --config ./path/to/vitest.config.ts
- Use
process.env.VITEST
to conditionally apply differnet configuration invite.config.ts
To configure vitest
itself, add test
property in your Vite config
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
test: {
// ...
}
})
By default, vitest
does not provide global APIs for explicitness. If you prefer to use the APIs globally like Jest, you can pass the --global
option to CLI or add global: true
in the config.
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
test: {
global: true
}
})
To get TypeScript working with the global APIs, add vitest/global
to the types
filed in your tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"types": [
"vitest/global"
]
}
}
If you are already using unplugin-auto-import
in your project, you can also use it directly for auto importing those APIs.
// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
AutoImport({
imports: ['vitest'],
dts: true // genreate TypeScript declaration
})
]
})
Pass --dom
option in CLI to enable browser mocking. Or the dom
flag in the config.
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
test: {
dom: true
}
})
Vitest by default uses jsdom for mocking, but it also support happy-dom, a faster alternative to jsdom. You can configure it with:
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
test: {
dom: 'happy-dom'
}
})
$ vitest -w
Vitest smartly searches the module graph and only rerun the related tests (just like how HMR works in Vite!).
Vitest works perfectly with c8
$ c8 vitest
{
"scripts": {
"test": "vitest",
"coverage": "c8 vitest"
}
}
For convenience, we also provide a shorthand for passing --coverage
option to CLI, which will wrap the process with c8
for you. Note when using the shorthand, you will lose the ability to pass additional options to c8
.
$ vitest --coverage
For more configuration available, please refer to c8's documentation.
You can use CLI to filter test files my name:
$ vitest basic
Will only execute test files that contain basic
, e.g.
basic.test.ts
basic-foo.test.ts
Use .skip
to avoid running certain suites or tests
describe.skip('skipped suite', () => {
it('test', () => {
// Suite skipped, no error
assert.equal(Math.sqrt(4), 3)
})
})
describe('suite', () => {
it.skip('skipped test', () => {
// Test skipped, no error
assert.equal(Math.sqrt(4), 3)
})
})
Use .only
to only run certain suites or tests
// Only this suite (and others marked with only) are run
describe.only('suite', () => {
it('test', () => {
assert.equal(Math.sqrt(4), 3)
})
})
describe('another suite', () => {
it('skipped test', () => {
// Test skipped, as tests are running in Only mode
assert.equal(Math.sqrt(4), 3)
})
it.only('test', () => {
// Only this test (and others marked with only) are run
assert.equal(Math.sqrt(4), 2)
})
})
Use .todo
to stub suites and tests that should be implemented
// An entry will be shown in the report for this suite
describe.todo('unimplemented suite')
// An entry will be shown in the report for this test
describe('suite', () => {
it.todo('unimplemented test')
})
Use .concurrent
in consecutive tests to run them in parallel
// The two tests marked with concurrent will be run in parallel
describe('suite', () => {
it('serial test', () => {
assert.equal(Math.sqrt(4), 3)
})
it.concurrent('concurrent test 1', () => {
assert.equal(Math.sqrt(4), 3)
})
it.concurrent('concurrent test 2', () => {
assert.equal(Math.sqrt(4), 3)
})
})
If you use .concurrent
in a suite, every tests in it will be run in parallel
// The two tests marked with concurrent will be run in parallel
describe.concurrent('suite', () => {
it('concurrent test 1', () => {
assert.equal(Math.sqrt(4), 3)
})
it('concurrent test 2', () => {
assert.equal(Math.sqrt(4), 3)
})
// No effect, same as not using .concurrent
it.concurrent('concurrent test 3', () => {
assert.equal(Math.sqrt(4), 3)
})
})
You can also use .skip
, .only
, and .todo
with concurrent suite and tests. All the following combinations are valid:
describe.concurrent(...)
describe.skip.concurrent(...)
describe.concurrent.skip(...)
describe.only.concurrent(...)
describe.concurrent.only(...)
describe.todo.concurrent(...)
describe.concurrent.todo(...)
it.concurrent(...)
it.skip.concurrent(...)
it.concurrent.skip(...)
it.only.concurrent(...)
it.concurrent.only(...)
it.todo.concurrent(...)
it.concurrent.todo(...)
Thanks to:
- @patak-js for the awesome package name!
- The Vite team for brainstorming the initial idea.
- @pi0 for the idea and implementation of using Vite to transform and bundle the server code.
- @lukeed for the work on uvu where we are inspired a lot from.
MIT License © 2021 Anthony Fu