跳至主要内容

运行测试

注意:此功能在 [email protected] 及更高版本中可用。

阅读迁移指南以了解如何在旧项目中启用它!

Create React App 使用 Jest 作为其测试运行器。为了准备此集成,我们对 Jest 进行了一次 重大改造,所以如果你几年前听说过它不好,那就再试一次吧。

Jest 是一个基于 Node 的运行器。这意味着测试始终在 Node 环境中运行,而不是在真实的浏览器中。这让我们能够实现快速的迭代速度并防止不稳定性。

虽然 Jest 通过 jsdom 提供了诸如 window 之类的浏览器全局变量,但它们只是对真实浏览器行为的近似值。Jest 旨在用于你的逻辑和组件的单元测试,而不是 DOM 特性。

如果你需要浏览器端到端测试,我们建议你使用单独的工具。它们超出了 Create React App 的范围。

文件名约定

Jest 将查找具有以下任何常用命名约定的测试文件

  • __tests__ 文件夹中具有 .js 后缀的文件。
  • 具有 .test.js 后缀的文件。
  • 具有 .spec.js 后缀的文件。

.test.js / .spec.js 文件(或 __tests__ 文件夹)可以位于 src 顶层文件夹下的任何深度。

我们建议将测试文件(或 __tests__ 文件夹)放在它们要测试的代码旁边,这样相对导入看起来更短。例如,如果 App.test.jsApp.js 在同一个文件夹中,测试只需要 import App from './App',而不是一个很长的相对路径。共置也有助于在大型项目中更快地找到测试。

命令行界面

当您运行 npm test 时,Jest 将以观察模式*启动。每次您保存文件时,它都会重新运行测试,就像 npm start 重新编译代码一样。

观察器包含一个交互式命令行界面,可以运行所有测试或专注于搜索模式。它以这种方式设计,以便您可以将其保持打开状态并享受快速重新运行。您可以从观察器在每次运行后打印的“观察器使用”说明中了解命令

Jest watch mode

*虽然我们建议在开发过程中以观察模式运行您的测试,但您可以通过传递 --watchAll=false 标志来禁用此行为。在大多数 CI 环境中,这将为您处理(请参阅 在 CI 服务器上)。

版本控制集成

默认情况下,当您运行 npm test 时,Jest 将只运行与自上次提交以来更改的文件相关的测试。这是一种优化,旨在使您的测试运行速度快,无论您有多少测试。但是,它假设您不会经常提交不通过测试的代码。

Jest 将始终明确地提到它只运行了与自上次提交以来更改的文件相关的测试。您也可以在观察模式下按 a 强制 Jest 运行所有测试。

Jest 将始终在 持续集成 服务器上运行所有测试,或者如果项目不在 Git 或 Mercurial 存储库中。

编写测试

要创建测试,请添加it()(或test())块,其中包含测试名称及其代码。您可以选择将它们包装在describe()块中以进行逻辑分组,但这既不是必需的,也不推荐。

Jest 提供了一个内置的expect()全局函数用于进行断言。一个基本的测试可能如下所示

import sum from './sum';

it('sums numbers', () => {
expect(sum(1, 2)).toEqual(3);
expect(sum(2, 2)).toEqual(4);
});

Jest 支持的所有expect()匹配器都在此处进行了详细的文档说明

您还可以使用jest.fn()expect(fn).toBeCalled() 来创建“间谍”或模拟函数。

测试组件

组件测试技术有很多种。它们从验证组件渲染时不会抛出异常的“冒烟测试”到浅渲染和测试部分输出,再到完整渲染和测试组件生命周期和状态变化。

不同的项目根据组件更改的频率以及它们包含的逻辑数量选择不同的测试权衡。如果您还没有决定测试策略,我们建议您从为组件创建基本的冒烟测试开始

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});

此测试将挂载组件并确保它在渲染过程中没有抛出异常。这种测试在付出很少的努力的情况下提供了很大的价值,因此它们非常适合作为起点,这也是您将在src/App.test.js中找到的测试。

当您遇到由更改组件引起的错误时,您将更深入地了解哪些部分值得在您的应用程序中进行测试。这可能是引入更多特定测试以断言特定预期输出或行为的好时机。

React 测试库

如果您想在隔离子组件的情况下测试组件,我们建议您使用react-testing-libraryreact-testing-library 是一个用于以类似于最终用户使用组件的方式测试 React 组件的库。它非常适合对 React 组件和应用程序进行单元测试、集成测试和端到端测试。它更直接地使用 DOM 节点,因此建议与jest-dom一起使用以改进断言。

要安装 react-testing-libraryjest-dom,您可以运行

npm install --save @testing-library/react @testing-library/jest-dom

或者,您可以使用 yarn

yarn add @testing-library/react @testing-library/jest-dom

如果您想避免在测试文件中使用样板代码,可以创建一个 src/setupTests.js 文件

// react-testing-library renders your components to document.body,
// this adds jest-dom's custom assertions
import '@testing-library/jest-dom';

以下是如何使用 react-testing-libraryjest-dom 测试 <App /> 组件是否渲染了 "Learn React" 的示例。

import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';

it('renders welcome message', () => {
render(<App />);
expect(screen.getByText('Learn React')).toBeInTheDocument();
});

react-testing-library 文档示例 中了解有关 react-testing-library 提供的用于促进测试异步交互以及从表单元素中进行选择的实用程序的更多信息。

使用第三方断言库

我们建议您使用 expect() 进行断言,使用 jest.fn() 进行间谍。如果您遇到问题,请 向 Jest 提交问题,我们会修复它们。我们打算继续改进它们以更好地支持 React,例如,支持 将 React 元素漂亮打印为 JSX

但是,如果您习惯使用其他库,例如 ChaiSinon,或者您有使用它们的现有代码想要移植过来,您可以像这样正常导入它们

import sinon from 'sinon';
import { expect } from 'chai';

然后像往常一样在测试中使用它们。

初始化测试环境

注意:此功能在 [email protected] 及更高版本中可用。

如果您的应用程序使用需要在测试中模拟的浏览器 API,或者您需要在运行测试之前进行全局设置,请在项目中添加 src/setupTests.js。它将在运行测试之前自动执行。

例如

src/setupTests.js

const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;

注意:请记住,如果您决定在创建 src/setupTests.js 之前“弹出”,生成的 package.json 文件将不会包含任何对它的引用,因此您应该手动在 Jest 的配置中创建属性 setupFilesAfterEnv,如下所示

"jest": {
// ...
"setupFilesAfterEnv": ["<rootDir>/src/setupTests.js"]
}

聚焦和排除测试

您可以用 xit() 替换 it() 来暂时排除测试的执行。

类似地,fit() 允许您专注于特定测试,而无需运行任何其他测试。

覆盖率报告

Jest 集成了覆盖率报告器,它与 ES6 兼容,无需配置。

运行 npm test -- --coverage(注意中间的额外 --)以包含类似这样的覆盖率报告

coverage report

请注意,带有覆盖率的测试运行速度要慢得多,因此建议将其与正常工作流程分开运行。

配置

Create React App 用于 Jest 的 默认配置 可以通过在您的 package.json 中添加以下任何支持的键到 Jest 配置来覆盖。

支持的覆盖

示例 package.json

{
"name": "your-package",
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!<rootDir>/node_modules/",
"!<rootDir>/path/to/dir/"
],
"coverageThreshold": {
"global": {
"branches": 90,
"functions": 90,
"lines": 90,
"statements": 90
}
},
"coverageReporters": ["text"],
"snapshotSerializers": ["my-serializer-module"]
}
}

持续集成

默认情况下,npm test 会运行带有交互式 CLI 的观察器。但是,您可以通过设置名为 CI 的环境变量来强制它运行一次测试并完成该过程。

使用 npm run build 创建应用程序构建时,默认情况下不会检查 linter 警告。与 npm test 一样,您可以通过设置环境变量 CI 来强制构建执行 linter 警告检查。如果遇到任何警告,则构建将失败。

流行的 CI 服务器默认情况下已经设置了环境变量 CI,但您也可以自己进行设置

在 CI 服务器上

Travis CI

  1. 按照 Travis 入门 指南将您的 GitHub 存储库与 Travis 同步。您可能需要在您的 个人资料 页面中手动初始化一些设置。
  2. 在您的 Git 仓库中添加一个 .travis.yml 文件。
language: node_js
node_js:
- 8
cache:
directories:
- node_modules
script:
- npm run build
- npm test
  1. 通过 git push 触发您的第一个构建。
  2. 如果需要,自定义您的 Travis CI 构建

CircleCI

按照 这篇文章 使用 Create React App 项目设置 CircleCI。

在您自己的环境中

Windows (cmd.exe)

set CI=true&&npm test
set CI=true&&npm run build

(注意:空格的缺失是故意的。)

Windows (Powershell)

($env:CI = "true") -and (npm test)
($env:CI = "true") -and (npm run build)

Linux,macOS (Bash)

CI=true npm test
CI=true npm run build

test 命令将强制 Jest 在 CI 模式下运行,并且测试将只运行一次,而不是启动监视器。

对于非 CI 环境,您可以传递 --watchAll=false 标志来禁用测试监视。

build 命令将检查 linter 警告,如果发现任何警告,则会失败。

禁用 jsdom

如果您知道您的任何测试都不依赖于 jsdom,您可以安全地设置 --env=node,并且您的测试将运行得更快。

  "scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
- "test": "react-scripts test"
+ "test": "react-scripts test --env=node"

为了帮助您做出决定,以下列出了需要 jsdom 的 API

相反,对于以下 API,不需要 jsdom

最后,对于 快照测试,也不需要 jsdom。

快照测试

快照测试是 Jest 的一项功能,它会自动生成组件的文本快照并将其保存到磁盘上,因此如果 UI 输出发生变化,您会收到通知,而无需手动编写任何关于组件输出的断言。 阅读有关快照测试的更多信息。

编辑器集成

如果您使用 Visual Studio Code,则有一个 Jest 扩展,它可以与 Create React App 开箱即用。这在使用文本编辑器时提供了许多 IDE 类功能:显示测试运行的状态以及潜在的失败消息内联,自动启动和停止监视器,并提供一键式快照更新。

VS Code Jest Preview