Skip to content
Vitest 3
Main Navigation 指南 & API配置浏览器模式高级 API
3.2.0
2.1.9
1.6.1
0.34.6

简体中文

English
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

简体中文

English
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

主题

Sidebar Navigation

简介

为什么选择 Vitest

快速入门

特性

配置 Vitest

API

测试 API 参考

模拟函数

Vi

expect

expectTypeOf

assert

assertType

指南

命令行界面

测试过滤

测试项目

报告器

覆盖率

快照

模拟

并行

类型测试

Vitest UI

源内测试

测试上下文

测试注解

测试环境

扩展匹配器

IDE 集成

调试

常见错误

迁移指南

迁移到 Vitest 3.0

从 Jest 迁移

性能

分析测试性能

性能优化

浏览器模式

高级 API

与其他测试运行器的比较

页面导航

特性 ​

  • Vite 的配置、转换器、解析器和插件支持
  • 使用与应用相同的配置来运行测试!
  • 智能且即时的观察模式,类似于测试中的 HMR!
  • 支持 Vue、React、Svelte、Lit、Marko 等的组件测试
  • 开箱即用的 TypeScript / JSX 支持
  • ESM 优先,支持顶级 await
  • 通过 Tinypool 实现多线程 Workers
  • 通过 Tinybench 支持基准测试
  • 支持对测试套件和测试进行过滤、超时设置和并发运行
  • 项目支持
  • 兼容 Jest 的快照
  • 内置 Chai 用于断言 + Jest expect 兼容的 API
  • 内置 Tinyspy 用于模拟
  • happy-dom 或 jsdom 用于 DOM 模拟
  • 浏览器模式支持在浏览器中运行组件测试
  • 通过 v8 或 istanbul 进行代码覆盖率统计
  • 类似 Rust 的源码内测试
  • 通过 expect-type 进行类型测试
  • 分片支持
  • 报告未处理的错误
通过视频学习如何编写你的第一个测试

测试、开发和构建之间的共享配置 ​

Vitest 能够复用 Vite 的配置、转换器、解析器和插件。这意味着你可以使用与应用相同的配置来运行测试。

在 配置 Vitest 中了解更多。

观察模式 ​

bash
$ vitest

当你修改源代码或测试文件时,Vitest 会智能分析模块依赖图,仅重新运行相关测试,类似于 Vite 中的 HMR!

在开发环境中,vitest 默认以 watch mode 启动;在 CI 环境中(当 process.env.CI 存在时),则智能地以 run mode 启动。你可以使用 vitest watch 或 vitest run 来明确指定所需的模式。

使用 --standalone 标志启动 Vitest,使其在后台运行。它不会运行任何测试,直到相关文件发生变化。如果源代码发生变化,Vitest 不会运行测试,除非导入该源代码的测试已被执行。

开箱即用的常见 Web 惯用法 ​

开箱即用地支持 ES Module / TypeScript / JSX / PostCSS。

线程 ​

默认情况下,Vitest 通过 Tinypool(Piscina 的轻量级分支)使用 node:child_process 在多个进程中运行测试文件,从而支持测试并行执行。如果你想进一步加快测试套件的速度,可以考虑启用 --pool=threads 来使用 node:worker_threads 运行测试(请注意,某些包可能不适用于此设置)。

要在单个线程或进程中运行测试,请参阅 poolOptions。

Vitest 还会隔离每个文件的运行环境,以确保一个文件中的环境修改不会影响其他文件。可以通过向 CLI 传递 --no-isolate 来禁用隔离(牺牲正确性换取运行性能)。

测试过滤 ​

Vitest 提供了多种方法来筛选要执行的测试用例,以加快测试速度,让你能够专注于开发。

在 测试过滤 中了解更多。

并发运行测试 ​

在连续的测试中使用 .concurrent,使其并行启动。

ts
import { describe, it } from 'vitest';

// 两个标记为 concurrent 的测试将并行启动
describe('suite', () => {
  it('serial test', async () => {
    /* ... */
  });
  it.concurrent('concurrent test 1', async ({ expect }) => {
    /* ... */
  });
  it.concurrent('concurrent test 2', async ({ expect }) => {
    /* ... */
  });
});

如果你在一个测试套件上使用 .concurrent,那么该套件中的所有测试都将并行执行。

ts
import { describe, it } from 'vitest';

// 此套件中的所有测试都将并行启动
describe.concurrent('suite', () => {
  it('concurrent test 1', async ({ expect }) => {
    /* ... */
  });
  it('concurrent test 2', async ({ expect }) => {
    /* ... */
  });
  it.concurrent('concurrent test 3', async ({ expect }) => {
    /* ... */
  });
});

你还可以将 .skip、.only 和 .todo 与并发套件和测试一起使用。在 API 参考 中阅读更多。

WARNING

运行并发测试时,快照和断言必须使用来自本地 测试上下文 的 expect,以确保正确识别对应的测试。

快照 ​

兼容 Jest 的 快照支持。

ts
import { expect, it } from 'vitest';

it('renders correctly', () => {
  const result = render();
  expect(result).toMatchSnapshot();
});

在 快照 中了解更多。

Chai 和 Jest expect 兼容性 ​

Chai 内置用于断言,并提供与 Jest expect 兼容的 API。

请注意,如果你正在使用添加匹配器的第三方库,将 test.globals 设置为 true 将提供更好的兼容性。

模拟 ​

Tinyspy 内置用于模拟,并在 vi 对象上提供 jest 兼容的 API。

ts
import { expect, vi } from 'vitest';

const fn = vi.fn();

fn('hello', 1);

expect(vi.isMockFunction(fn)).toBe(true);
expect(fn.mock.calls[0]).toEqual(['hello', 1]);

fn.mockImplementation((arg: string) => arg);

fn('world', 2);

expect(fn.mock.results[1].value).toBe('world');

Vitest 支持使用 happy-dom 或 jsdom 来模拟 DOM 和浏览器 API。它们不随 Vitest 一起提供,你需要单独安装它们:

bash
$ npm i -D happy-dom
bash
$ npm i -D jsdom

之后,在你的配置文件中更改 environment 选项:

ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'happy-dom', // 或 'jsdom', 'node'
  },
});

在 模拟 中了解更多。

覆盖率 ​

Vitest 支持通过 v8 进行原生代码覆盖率统计,以及通过 istanbul 进行插桩代码覆盖率统计。

json
{
  "scripts": {
    "test": "vitest",
    "coverage": "vitest run --coverage"
  }
}

在 覆盖率 中了解更多。

源码内测试 ​

Vitest 还提供了一种在源代码中与实现一起运行测试的方法,类似于 Rust 的模块测试。

这使得测试能够与实现共享相同的闭包,并且在不导出的情况下测试私有状态。同时,这也使得开发过程中的反馈循环更加紧密。

ts
// 实现
export function add(...args: number[]): number {
  return args.reduce((a, b) => a + b, 0);
}

// 源码内测试套件
if (import.meta.vitest) {
  const { it, expect } = import.meta.vitest;
  it('add', () => {
    expect(add()).toBe(0);
    expect(add(1)).toBe(1);
    expect(add(1, 2, 3)).toBe(6);
  });
}

在 源码内测试 中了解更多。

基准测试 实验性 ​

你可以通过 Tinybench 使用 bench 函数运行基准测试,以比较性能结果。

ts
import { bench, describe } from 'vitest';

describe('sort', () => {
  bench('normal', () => {
    const x = [1, 5, 4, 2, 3];
    x.sort((a, b) => {
      return a - b;
    });
  });

  bench('reverse', () => {
    const x = [1, 5, 4, 2, 3];
    x.reverse().sort((a, b) => {
      return a - b;
    });
  });
});
基准测试报告基准测试报告

类型测试 实验性 ​

你可以编写测试来捕获类型回归问题。Vitest 附带 expect-type 包,为你提供类似且易于理解的 API。

ts
import { assertType, expectTypeOf, test } from 'vitest';
import { mount } from './mount.js';

test('my types work properly', () => {
  expectTypeOf(mount).toBeFunction();
  expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();

  // @ts-expect-error name is a string
  assertType(mount({ name: 42 }));
});

分片 ​

使用 --shard 和 --reporter=blob 标志在不同的机器上运行测试。 所有测试和覆盖率结果都可以在 CI 流水线结束时,使用 --merge-reports 命令进行合并:

bash
vitest --shard=1/2 --reporter=blob --coverage
vitest --shard=2/2 --reporter=blob --coverage
vitest --merge-reports --reporter=junit --coverage

有关更多信息,请参阅 提高性能 | 分片。

环境变量 ​

Vitest 专门从 .env 文件中自动加载以 VITE_ 为前缀的环境变量,以保持与前端相关测试的兼容性,并遵循 Vite 既定的约定。若要从 .env 文件中加载所有环境变量,你可以使用从 vite 导入的 loadEnv 方法:

ts
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';

export default defineConfig(({ mode }) => ({
  test: {
    // mode 定义了在存在时,应选择哪个 ".env.{mode}" 文件
    env: loadEnv(mode, process.cwd(), ''),
  },
}));

未处理的错误 ​

默认情况下,Vitest 会捕获并报告所有未处理的拒绝、未捕获的异常(在 Node.js 中)以及 错误 事件(在浏览器中)。

你可以通过手动捕获这些错误来禁用此行为。Vitest 假定回调已由你处理,因此不会报告该错误。

ts
// 在 Node.js 中
process.on('unhandledRejection', () => {
  // 你自己的处理程序
});

process.on('uncaughtException', () => {
  // 你自己的处理程序
});
ts
// 在浏览器中
window.addEventListener('error', () => {
  // 你自己的处理程序
});

window.addEventListener('unhandledrejection', () => {
  // 你自己的处理程序
});

或者,你也可以使用 dangerouslyIgnoreUnhandledErrors 选项来忽略已报告的错误。Vitest 仍然会报告这些错误,但它们不会影响测试结果(退出代码不会改变)。

如果你需要测试错误未被捕获,你可以创建一个如下所示的测试:

ts
test('my function throws uncaught error', async ({ onTestFinished }) => {
  onTestFinished(() => {
    // 如果在测试期间从未调用过该事件,
    // 请确保在下一个测试开始之前将其移除。
    process.removeAllListeners('unhandledrejection');
  });

  return new Promise((resolve, reject) => {
    process.once('unhandledrejection', error => {
      try {
        expect(error.message).toBe('my error');
        resolve();
      } catch (error) {
        reject(error);
      }
    });

    callMyFunctionThatRejectsError();
  });
});
Pager
上一页快速入门
下一页配置 Vitest

基于 MIT 许可证 发布。

版权所有 (c) 2021-Present Vitest Team

https://vitest.dev/guide/features

基于 MIT 许可证 发布。

版权所有 (c) 2021-Present Vitest Team