If you used a previous version of this template, you would probably be using ava as the testing framework. whereas now
the template makes use of vitest. Below is a simple migration guide on moving from ava to vitest.
Note: This template has also migrated to vite from babel and rollup directly, so some parts of this will assume
the use of vite.
First, remove Ava if you haven’t already:
npm uninstall avaThen, install Vitest:
npm install -D vitestIf you’re using Vite, like this template, you can also integrate Vitest directly with it:
npm install -D vitest viteVitest configuration is typically handled in vite.config.js or vite.config.ts. However, if you prefer a separate
configuration file, you can create a vitest.config.ts file.
Here's an example of vite.config.ts with Vitest setup:
// vite.config.ts
import {defineConfig} from 'vite';
import {configDefaults} from 'vitest/config';
export default defineConfig({
test: {
globals: true, // Ava's globals are auto-enabled, but for Vitest, specify it here
environment: 'node', // Similar to Ava’s node environment
exclude: [...configDefaults.exclude, 'dist'], // Customize excludes as needed
setupFiles: './vitest.setup.ts', // If you have global setup similar to Ava’s hooks
coverage: {
provider: 'istanbul' // This template uses istanbul for coverage
},
},
});Ava uses test as the default import, while Vitest lets you import directly from vitest with a similar API. Here’s a
comparison:
import test from 'ava';
test('basic test', t => {
t.is(1 + 1, 2);
});import {test, expect} from 'vitest';
test('basic test', () => {
expect(1 + 1).toBe(2);
});Ava uses its own assertion library, while Vitest uses Jest-like assertions by default.
| Ava | Vitest |
|---|---|
| t.is(a, b) | expect(a).toBe(b) |
| t.deepEqual | expect(a).toEqual(b) |
| t.truthy | expect(a).toBeTruthy() |
| t.false | expect(a).toBeFalsy() |
You’ll need to replace Ava assertions with Vitest’s expect.
Both Ava and Vitest have setup and teardown hooks, but with slightly different names.
| Ava | Vitest |
|---|---|
| test.before | beforeAll |
| test.beforeEach | beforeEach |
| test.after | afterAll |
| test.afterEach | afterEach |
test.before(() => {
// runs before all tests
});
test.afterEach(() => {
// runs after each test
});import {beforeAll, afterEach} from 'vitest';
beforeAll(() => {
// runs before all tests
});
afterEach(() => {
// runs after each test
});Ava allows async tests with async functions, and Vitest works the same way but uses a simpler expect pattern.
test('async test', async t => {
const data = await fetchData();
t.is(data, 'expected value');
});test('async test', async () => {
const data = await fetchData();
expect(data).toBe('expected value');
});Vitest has built-in support for snapshot testing, similar to Jest. Ava doesn’t have built-in support for snapshots,
so if you were using a separate library for it, you can replace it with Vitest’s expect().toMatchSnapshot().
test('snapshot test', () => {
const obj = {foo: 'bar'};
expect(obj).toMatchSnapshot();
});Vitest integrates with c8 for coverage, while Ava requires external tools like nyc. Vite can also use
nyc (istanbul)
as shown in the example vitest.config.ts
npm install -D @vitest/coverage-istanbulRun tests with coverage:
vitest --coverageCoverage reports will be generated in the coverage directory by default.
- In Ava, you might have used
npx avaor"test": "ava". - In Vitest, you’ll run
vitestor add it to your package.json:
{
//... other config
"scripts": {
"test": "vitest --run",
// Vitest will run with --watch by default, so --run forces a single run and terminate
"test:watch": "vitest"
}
}To integrate with Vite, you can also run:
vite testThere are some key differences between ava and vitest:
- Previously,
avawould run the tests once they were output to thedistdirectory as.jsfiles, whilevitestwill run the tests as.tsfile in thesrcdirectory. vitestby default expects that tests are named as*.test.tsor*.spec.ts. This can be changed, but we prefer to keep to the defaults for familiarity.