All skills
antfu avatar

/vitest

@d02c484 official
by Anthony Fuantfu/skills5.9k stars
335

Vitest fast unit testing framework powered by Vite with Jest-compatible API. Use when writing tests, mocking, configuring coverage, or working with test filtering and fixtures.

Use this Skill: https://skilld.dev/gh/antfu/skills/vitest

This session only. Nothing lands on disk.

referencescore-test-api.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Test API

Basic Test

import { expect, test } from 'vitest'

test('adds numbers', () => {
  expect(1 + 1).toBe(2)
})

// Alias: it
import { it } from 'vitest'

it('works the same', () => {
  expect(true).toBe(true)
})

Async Tests

test('async test', async () => {
  const result = await fetchData()
  expect(result).toBeDefined()
})

// Promises are automatically awaited
test('returns promise', () => {
  return fetchData().then(result => {
    expect(result).toBeDefined()
  })
})

Test Options

// Timeout (default: 5000ms)
test('slow test', async () => {
  // ...
}, 10_000)

// Or with options object
test('with options', { timeout: 10_000, retry: 2 }, async () => {
  // ...
})

Test Modifiers

Skip Tests

test.skip('skipped test', () => {
  // Won't run
})

// Conditional skip
test.skipIf(process.env.CI)('not in CI', () => {})
test.runIf(process.env.CI)('only in CI', () => {})

// Dynamic skip via context
test('dynamic skip', ({ skip }) => {
  skip(someCondition, 'reason')
  // ...
})

Focus Tests

test.only('only this runs', () => {
  // Other tests in file are skipped
})

Todo Tests

test.todo('implement later')

test.todo('with body', () => {
  // Not run, shows in report
})

Failing Tests

test.fails('expected to fail', () => {
  expect(1).toBe(2) // Test passes because assertion fails
})

Concurrent Tests

// Run tests in parallel
test.concurrent('test 1', async ({ expect }) => {
  // Use context.expect for concurrent tests
  expect(await fetch1()).toBe('result')
})

test.concurrent('test 2', async ({ expect }) => {
  expect(await fetch2()).toBe('result')
})

Opt Out of Concurrency

test.sequential was removed in v5. Use concurrent: false to opt a test out of inherited or globally configured concurrency:

test('must run alone', { concurrent: false }, async () => {})

Parameterized Tests

test.each

test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) = %i', (a, b, expected) => {
  expect(a + b).toBe(expected)
})

// With objects
test.each([
  { a: 1, b: 1, expected: 2 },
  { a: 1, b: 2, expected: 3 },
])('add($a, $b) = $expected', ({ a, b, expected }) => {
  expect(a + b).toBe(expected)
})

// Template literal
test.each`
  a    | b    | expected
  ${1} | ${1} | ${2}
  ${1} | ${2} | ${3}
`('add($a, $b) = $expected', ({ a, b, expected }) => {
  expect(a + b).toBe(expected)
})

test.for

Preferred over .each - doesn't spread arrays:

test.for([
  [1, 1, 2],
  [1, 2, 3],
])('add(%i, %i) = %i', ([a, b, expected], { expect }) => {
  // Second arg is TestContext
  expect(a + b).toBe(expected)
})

v5: titles are formatted with pretty-format, and a string interpolated through a $ placeholder is no longer quoted (case $id → case a1, not case 'a1'). Interpolated-value length is capped by taskTitleValueFormatTruncate (default 40).

Test Context

First argument provides context utilities:

test('with context', ({ expect, skip, task, signal, annotate }) => {
  console.log(task.name)        // Test metadata
  skip(someCondition, 'reason') // Skip dynamically
  expect(1).toBe(1)             // Context-bound expect
})

// signal (3.2+): AbortSignal aborted on timeout/cancel/bail
test('aborts on timeout', async ({ signal }) => {
  await fetch('/resource', { signal })
}, 2000)

// annotate (3.2+): attach notes shown by the reporter
test('annotated', async ({ annotate }) => {
  await annotate('see issue #123', 'issues')
})

Custom Test with Fixtures

Prefer the builder pattern (4.1+) for automatic type inference:

import { test as base } from 'vitest'

const test = base
  .extend('db', async ({}, { onCleanup }) => {
    const db = await createDb()
    onCleanup(() => db.close()) // runs after the test/scope
    return db
  })

test('query', async ({ db }) => {
  const users = await db.query('SELECT * FROM users')
  expect(users).toBeDefined()
})

See features-context for fixture scopes, test.override, and the Playwright-compatible object syntax.

Retry Configuration

test('flaky test', { retry: 3 }, async () => {
  // Retries up to 3 times on failure
})

// Advanced retry options
test('with delay', {
  retry: {
    count: 3,
    delay: 1000,
    condition: /timeout/i, // Only retry on timeout errors
  },
}, async () => {})

Tags

Tags must be declared in config first, then applied to tests (4.1+):

test('database test', { tags: ['db', 'slow'] }, async () => {})

// Run with a tag expression:
// vitest --tagsFilter "db && !flaky"

See features-test-tags for defining tags and filter syntax.

Benchmarks (v5)

bench is no longer a top-level import — it is a test-context fixture used inside test():

// file must match benchmark.include (e.g. *.bench.ts)
test('sort', async ({ bench }) => {
  await bench('Array.sort', () => [3, 1, 2].sort()).run()
})

Key Points

  • Pass options as the second argument; the 3rd-arg options object was removed in v4 (a trailing timeout number is still allowed)
  • Tests with no body are marked as todo
  • test.only throws in CI unless allowOnly: true
  • Use context's expect for concurrent tests and snapshots
  • Function name is used as test name if passed as first arg
  • test.sequential was removed in v5 — use { concurrent: false }
<!-- Source references: - https://vitest.dev/api/test.html -->

Source: SKILL.md on GitHub

No alerts3d5 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill provides comprehensive documentation and reference material for the Vitest testing framework. It covers configuration, CLI usage, mocking, coverage, and advanced features like type testing and benchmarking. No security issues were detected; the instructions follow standard development and testing practices.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

  • Runlayer7mo

    1/18 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at d02c484. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 4 days ago
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.9.25",
  "source": "Generated from https://github.com/vitest-dev/vitest, scripts located at https://github.com/antfu/skills"
}

README badge

README badge for antfu/skills/vitest

Vitest is a Jest-compatible unit testing framework powered by Vite, with native ESM, TypeScript, and JSX support. Use it for writing tests with smart watch mode, mocking, fixtures, coverage reporting, and snapshot testing in projects already using Vite.

Generated from the current SKILL.md.

Is Vitest a drop-in replacement for Jest?
Mostly. Vitest provides a Jest-compatible API and can run most Jest test suites without modification, but it uses Vite's transformation pipeline instead of Jest's, so some edge cases may differ.
Does Vitest require configuration?
No. It natively supports ESM, TypeScript, and JSX out of the box and shares Vite's config, transformers, and resolvers, so many projects need minimal or no additional setup.
What coverage providers does Vitest support?
Vitest includes built-in coverage via V8 or Istanbul providers.
Can I run tests in parallel?
Yes. Vitest uses multi-threaded workers for parallel test execution and supports sharding across multiple processes.
What test environments are available?
Vitest supports node, jsdom, happy-dom, and custom environments.

Generated from the current SKILL.md. These answers refresh after source changes.