文档
Storybook 文档

测试覆盖率

观看视频教程

测试覆盖率是指衡量现有测试是否完全覆盖代码的实践。这意味着要找出当前未被测试的区域,例如:条件、逻辑分支、函数和变量。

覆盖率测试会根据一套行业认可的最佳实践检查已插桩的代码。它们充当质量保证的最后一道防线,以提高测试套件的质量。

使用覆盖率插件进行代码插桩

Storybook 提供了一个官方的 测试覆盖率插件。由 Istanbul 提供支持,该插件允许对 JavaScript 生态系统中最常用的框架和构建器进行开箱即用的代码插桩。

设置覆盖率插件

该插件旨在与现代测试工具(例如 Playwright)协同工作,自动插桩代码并生成代码覆盖率数据。为了获得最佳体验,我们建议将 测试运行器 与覆盖率插件结合使用以运行测试。

运行以下命令安装插件。

npm install @storybook/addon-coverage --save-dev

更新 Storybook 配置(在 .storybook/main.js|ts 中)以包含覆盖率插件。

.storybook/main.ts
// Replace your-framework with the framework and builder you are using (e.g., react-webpack5, vue3-webpack5)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  stories: [],
  addons: [
    // Other Storybook addons
    '@storybook/addon-coverage', //👈 Registers the addon
  ],
};
 
export default config;

使用以下命令启动 Storybook

npm run storybook

最后,打开一个新的终端窗口并使用以下命令运行测试运行器

npm run test-storybook -- --coverage

Coverage test output

配置

默认情况下,@storybook/addon-coverage 为 Storybook 提供零配置支持,并通过 istanbul-lib-instrumentWebpack 进行代码插桩,或通过 vite-plugin-istanbulVite 进行代码插桩。但是,您可以扩展 Storybook 配置文件(即 .storybook/main.js|ts)并为插件提供其他选项。以下是按构建器划分的可用选项以及如何使用它们的示例。

.storybook/main.ts
// For Vite support add the following import
// import type { AddonOptionsVite } from '@storybook/addon-coverage';
 
import type { AddonOptionsWebpack } from '@storybook/addon-coverage';
 
// Replace your-framework with the framework and builder you are using (e.g., react-webpack5, vue3-webpack5)
import type { StorybookConfig } from '@storybook/your-framework';
 
const coverageConfig: AddonOptionsWebpack = {
  istanbul: {
    include: ['**/stories/**'],
    exclude: ['**/exampleDirectory/**'],
  },
};
 
const config: StorybookConfig = {
  stories: [],
  addons: [
    // Other Storybook addons
    {
      name: '@storybook/addon-coverage',
      options: coverageConfig,
    },
  ],
};
 
export default config;
Vite 选项描述类型
checkProd配置插件以在生产环境中跳过插桩
options: { istanbul: { checkProd: true,}}
布尔值
cwd配置覆盖率测试的工作目录。
默认为 process.cwd()
options: { istanbul: { cwd: process.cwd(),}}
字符串
cypressVITE_COVERAGE 环境变量替换为 CYPRESS_COVERAGE
需要 Cypress 的 代码覆盖率
options: { istanbul: { cypress: true,}}
布尔值
exclude使用提供的文件或目录列表覆盖 默认排除列表,以从覆盖率中排除这些文件或目录
options: { istanbul: { exclude: ['**/stories/**'],}}
Array<String>string
extension使用提供的文件扩展名列表扩展 默认扩展名列表,以包含在覆盖率中
options: { istanbul: { extension: ['.js', '.cjs', '.mjs'],}}
Array<String>string
forceBuildInstrument配置插件以在构建模式中添加插桩
options: { istanbul: { forceBuildInstrument: true,}}
布尔值
include选择要收集覆盖率的文件
options: { istanbul: { include: ['**/stories/**'],}}
Array<String>string
nycrcPath定义现有 nyc 配置文件 的相对路径
options: { istanbul: { nycrcPath: '../nyc.config.js',}}
字符串
requireEnv通过授予对 env 变量的访问权限来覆盖 VITE_COVERAGE 环境变量的值
options: { istanbul: { requireEnv: true,}}
布尔值
Webpack 5 选项描述类型
autoWrap通过将程序代码包装在函数中来提供对顶层 return 语句的支持
options: { istanbul: { autoWrap: true,}}
布尔值
compact压缩插桩代码的输出。对调试很有用
options: { istanbul: { compact: false,}}
布尔值
coverageVariable定义 Istanbul 用于存储覆盖率结果的全局变量名
options: { istanbul: { coverageVariable: '__coverage__',}}
字符串
cwd配置覆盖率测试的工作目录。
默认为 process.cwd()
options: { istanbul: { cwd: process.cwd(),}}
字符串
debug在插桩过程中启用调试模式以获取其他日志信息
options: { istanbul: { debug: true,}}
布尔值
esModules启用对 ES 模块语法的支持
options: { istanbul: { esModules: true,}}
布尔值
exclude使用提供的文件或目录列表覆盖 默认排除列表,以从覆盖率中排除这些文件或目录
options: { istanbul: { exclude: ['**/stories/**'],}}
Array<String>string
extension使用提供的文件扩展名列表扩展 默认扩展名列表,以包含在覆盖率中
options: { istanbul: { extension: ['.js', '.cjs', '.mjs'],}}
Array<String>string
include选择要收集覆盖率的文件
options: { istanbul: { include: ['**/stories/**'],}}
Array<String>string
nycrcPath定义现有 nyc 配置文件 的相对路径
options: { istanbul: { nycrcPath: '../nyc.config.js',}}
字符串
preserveComments在插桩代码中包含注释
options: { istanbul: { preserveComments: true,}}
布尔值
produceSourceMap配置 Instanbul 为插桩代码生成源映射
options: { istanbul: { produceSourceMap: true,}}
布尔值
sourceMapUrlCallback定义在生成源映射时使用文件名和源映射 URL 调用的回调函数
选项:{ istanbul:{ sourceMapUrlCallback: (文件名, url) => {},}}
函数

其他覆盖率报告工具呢?

默认情况下,代码覆盖率测试与 Storybook 的测试运行器和 @storybook/addon-coverage 无缝衔接。但是,这并不意味着您不能使用其他报告工具(例如,Codecov)。例如,如果您正在使用 LCOV,您可以使用生成的输出(在 coverage/storybook/coverage-storybook.json 中)并使用以下方法创建自己的报告

npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook

故障排除

在其他框架中运行测试覆盖率

如果您打算在具有特殊文件的框架(如 Vue 3 或 Svelte)中运行覆盖率测试,则需要调整您的配置并启用所需的文件扩展名。例如,如果您使用的是 Vue,则需要将以下内容添加到您的 nyc 配置文件中(即 .nycrc.jsonnyc.config.js

.nyc.config.js
export default {
  // Other configuration options
  extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue'],
};

覆盖率插件不支持优化构建

如果您使用 --test 标志生成了一个针对性能优化的生产构建,并且您正在使用覆盖率插件对 Storybook 运行测试,您可能会遇到覆盖率插件无法对您的代码进行检测的情况。这是由于标志的工作方式,因为它会删除对性能有影响的插件(例如,Docs覆盖率插件)。要解决此问题,您需要调整您的 Storybook 配置文件(即 .storybook/main.js|ts)并包含 disabledAddons 选项,以允许插件以牺牲构建速度为代价运行测试。

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    '@storybook/addon-coverage',
  ],
  build: {
    test: {
      disabledAddons: ['@storybook/addon-docs', '@storybook/addon-essentials/docs'],
    },
  },
};
 
export default config;

覆盖率插件不支持检测到的代码

由于 覆盖率插件 基于 Webpack5 加载器和 Vite 插件进行代码检测,因此不依赖于这些库的框架(例如,使用 Webpack 配置的 Angular)将需要额外的配置才能启用代码检测。在这种情况下,您可以参考以下 存储库 获取更多信息。

了解其他 UI 测试