Skip to content
Vitest 1
Main Navigation 指南API配置高级
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

快速开始

特性

工作区

命令行界面

测试筛选

报告器

代码覆盖率

快照(Snapshot)

模拟(Mocking)

类型测试

Vitest UI

浏览器模式

源码内测试

测试上下文

测试环境

扩展匹配器

IDE 集成

调试

与其他测试运行器的比较

迁移指南

常见错误

提升性能

API

测试 API 索引

模拟函数

Vi

expect

expectTypeOf

assert(断言)

assertType

配置

管理 Vitest 配置文件

配置 Vitest

页面导航

快照(Snapshot) ​

通过 Vue School 的视频学习快照

当需要确保函数输出不会意外更改时,快照测试是一个非常有用的工具。

使用快照时,Vitest 会获取给定值的快照,然后将其与存储在测试文件旁边的参考快照文件进行比较。如果两个快照不匹配,测试将失败:这可能意味着更改是意外的,或者你需要将参考快照更新为结果的新版本。

使用快照 ​

要为一个值创建快照,你可以使用 expect() API 中的 toMatchSnapshot():

ts
function toUpperCase(str: string) {
  return str;
}
// ---cut---
import { expect, it } from 'vitest';

it('toUpperCase', () => {
  const result = toUpperCase('foobar');
  expect(result).toMatchSnapshot();
});

第一次运行此测试时,Vitest 会创建一个如下所示的快照文件:

js
// Vitest Snapshot v1, https://www.getbook.com/zh-cn/book/vitest-1/guide/snapshot

exports['toUpperCase 1'] = '"FOOBAR"';

快照文件应与代码更改一起提交,并作为代码审查过程的一部分进行审查。在随后的测试运行中,Vitest 会将渲染的输出与之前的快照进行比较。如果它们匹配,测试将通过。如果它们不匹配,则测试运行器检测到你的代码中可能存在需要修复的错误,或者实现已更改,因此需要更新快照。

WARNING

当在异步并发测试中使用快照时,必须使用来自本地测试上下文的 expect,以确保检测到正确的测试。

内联快照 ​

类似地,你可以使用 toMatchInlineSnapshot() 将快照以内联方式存储在测试文件中。

ts
function toUpperCase(str: string) {
  return str;
}
// ---cut---
import { expect, it } from 'vitest';

it('toUpperCase', () => {
  const result = toUpperCase('foobar');
  expect(result).toMatchInlineSnapshot();
});

Vitest 不会创建额外的快照文件,而是直接修改测试文件,将快照内容更新为字符串:

ts
function toUpperCase(str: string) {
  return str;
}
// ---cut---
import { expect, it } from 'vitest';

it('toUpperCase', () => {
  const result = toUpperCase('foobar');
  expect(result).toMatchInlineSnapshot('"FOOBAR"');
});

这允许你直接查看预期的输出,而无需在不同文件之间切换。

WARNING

当在异步并发测试中使用快照时,必须使用来自本地测试上下文的 expect,以确保检测到正确的测试。

更新快照 ​

当实际值与快照不匹配时,测试将会失败,并显示两者之间的差异。如果快照的更改是预期的,你需要根据当前状态更新快照。

在监听模式下,你可以按终端中的 u 键来直接更新失败的快照。

或者你可以在 CLI 中使用 --update 或 -u 标志来使 Vitest 更新快照。

bash
vitest -u

文件快照 ​

当调用 toMatchSnapshot() 时,所有快照都存储在格式化的 snap 文件中。这意味着需要转义快照字符串中的某些特殊字符,例如双引号 " 和反引号 ```。此外,快照内容的语法高亮可能会丢失(如果快照内容使用某种编程语言)。

为了改善这种情况,我们引入了 toMatchFileSnapshot() 以便将快照显式地存储在文件中。这允许你为快照文件指定任何文件扩展名,并使它们更具可读性。

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

it('render basic', async () => {
  const result = renderHTML(h('div', { class: 'foo' }));
  await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});

它会将结果与 ./test/basic.output.html 文件的内容进行比较。可以使用 --update 标志将更新后的内容写回文件。

图像快照 ​

也可以使用 jest-image-snapshot 对图像进行快照。

bash
npm i -D jest-image-snapshot
ts
test('image snapshot', () => {
  expect(readFileSync('./test/stubs/input-image.png')).toMatchImageSnapshot();
});

你可以在 examples/image-snapshot 示例中找到更多信息。

自定义序列化器 ​

你可以添加自己的逻辑来更改快照的序列化方式。与 Jest 类似,Vitest 提供了用于内置 JavaScript 类型、HTML 元素、ImmutableJS 和 React 元素的默认序列化器。

您可以通过使用 expect.addSnapshotSerializer API 显式添加自定义序列化器。

ts
expect.addSnapshotSerializer({
  serialize(val, config, indentation, depth, refs, printer) {
    // `printer` 是一个使用现有插件序列化值的函数。
    return `Pretty foo: ${printer(val.foo, config, indentation, depth, refs)}`;
  },
  test(val) {
    return val && Object.prototype.hasOwnProperty.call(val, 'foo');
  },
});

我们还支持 snapshotSerializers 选项来隐式添加自定义序列化器。

ts
import { SnapshotSerializer } from 'vitest';

export default {
  serialize(val, config, indentation, depth, refs, printer) {
    // `printer` 是一个使用现有插件序列化值的函数。
    return `Pretty foo: ${printer(val.foo, config, indentation, depth, refs)}`;
  },
  test(val) {
    return val && Object.prototype.hasOwnProperty.call(val, 'foo');
  },
} satisfies SnapshotSerializer;
ts
import { defineConfig } from 'vite';

export default defineConfig({
  test: {
    snapshotSerializers: ['path/to/custom-serializer.ts'],
  },
});

添加如下测试后:

ts
test('foo snapshot test', () => {
  const bar = {
    foo: {
      x: 1,
      y: 2,
    },
  };

  expect(bar).toMatchSnapshot();
});

你将获得以下快照:

Pretty foo: Object {
  "x": 1,
  "y": 2,
}

我们使用 Jest 的 pretty-format 库来序列化快照。你可以在这里阅读更多相关信息:pretty-format。

与 Jest 的区别 ​

Vitest 提供了与 Jest 几乎兼容的快照功能,但有一些例外:

1. 快照文件中的注释头不同 {#_1-comment-header-in-the-snapshot-file-is-different} ​

diff
- // Jest Snapshot v1, https://goo.gl/fbAQLP
+ // Vitest Snapshot v1, https://www.getbook.com/zh-cn/book/vitest-1/guide/snapshot

这不会影响功能,但可能会影响从 Jest 迁移项目时的提交差异。

2. printBasicPrototype 默认为 false {#_2-printbasicprototype-is-default-to-false} ​

Jest 和 Vitest 的快照都由 pretty-format 提供支持。在 Vitest 中,我们将 printBasicPrototype 默认设置为 false,以提供更清晰的快照输出。而在 Jest <29.0.0 中,它默认为 true。

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

test('snapshot', () => {
  const bar = [
    {
      foo: 'bar',
    },
  ];

  // in Jest
  expect(bar).toMatchInlineSnapshot(`
    Array [
      Object {
        "foo": "bar",
      },
    ]
  `);

  // in Vitest
  expect(bar).toMatchInlineSnapshot(`
    [
      {
        "foo": "bar",
      },
    ]
  `);
});

我们认为,从可读性和整体开发者体验 (DX) 角度来看,这是一个更合理的默认值。如果你仍然喜欢 Jest 的行为,你可以更改你的配置:

ts
// vitest.config.js
export default defineConfig({
  test: {
    snapshotFormat: {
      printBasicPrototype: true,
    },
  },
});

3. Chevron > 用作分隔符,而不是冒号 : 用于自定义消息 {#_3-chevron-is-used-as-a-separator-instead-of-colon-for-custom-messages} ​

当在创建快照文件时传递自定义消息时,Vitest 使用尖括号 > 符号作为分隔符,而不是冒号 :,以提高可读性。

对于以下示例测试代码:

js
test('toThrowErrorMatchingSnapshot', () => {
  expect(() => {
    throw new Error('error');
  }).toThrowErrorMatchingSnapshot('hint');
});

在 Jest 中,快照将是:

console
exports[`toThrowErrorMatchingSnapshot: hint 1`] = `"error"`;

在 Vitest 中,等效的快照将是:

console
exports[`toThrowErrorMatchingSnapshot > hint 1`] = `[Error: error]`;

4. toThrowErrorMatchingSnapshot 和 toThrowErrorMatchingInlineSnapshot 的默认 Error 快照不同 {#_4-default-error-snapshot-is-different-for-tothrowerrormatchingsnapshot-and-tothrowerrormatchinginlinesnapshot} ​

js
import { expect, test } from 'vitest';
// ---cut---
test('snapshot', () => {
  //
  // in Jest
  //

  expect(new Error('error')).toMatchInlineSnapshot(`[Error: error]`);

  // Jest 对 `Error` 实例进行 `Error.message` 快照
  expect(() => {
    throw new Error('error');
  }).toThrowErrorMatchingInlineSnapshot(`"error"`);

  //
  // in Vitest
  //

  expect(new Error('error')).toMatchInlineSnapshot(`[Error: error]`);

  expect(() => {
    throw new Error('error');
  }).toThrowErrorMatchingInlineSnapshot(`[Error: error]`);
});
Pager
上一页代码覆盖率
下一页模拟(Mocking)

基于 MIT 许可证 发布。

版权所有 (c) 2024 Mithril Contributors

https://v1.vitest.dev/guide/snapshot

基于 MIT 许可证 发布。

版权所有 (c) 2024 Mithril Contributors