首页指南参考教程

单元测试

了解如何设置和配置 jest-expo 包来为项目编写单元测试和快照测试。


Jest 是使用最广泛的 JavaScript 单元测试框架。在本指南中,你将了解如何在项目中设置 Jest、编写单元测试、快照测试,以及在将 Jest 与 React Native 结合使用时构建测试的最佳实践。

¥Jest is the most widely used JavaScript unit testing framework. In this guide, you'll learn how to set up Jest in your project, write a unit test, write a snapshot test, and best practices for structuring your tests when using Jest with React Native.

你还将使用 jest-expo 包,这是一个 Jest 预设,模拟 Expo SDK 的原生部分并处理大部分配置。

¥You'll also use the jest-expo package, which is a Jest preset and mocks the native part of the Expo SDK and handles most of the configuration.

安装

¥Installation

要在项目中安装 jest-expo,请运行以下命令:

¥To install jest-expo in your project, run the following command:

Terminal
# For all other package managers
npx expo install -- --save-dev jest-expo jest

# For yarn
yarn add -D jest-expo jest
如果你使用 TypeScript,则还要安装 @types/jest 作为开发依赖。

然后,更新 package.json 以添加用于运行测试的脚本,并添加使用 jest-expo 中的基本配置的预设:

¥Then, update package.json to add a script for running tests and add the preset for using the base configuration from jest-expo:

package.json
"scripts": {
  %%placeholder-start%%... %%placeholder-end%%
  "test": "jest"
},
%%placeholder-start%%... %%placeholder-end%%
"jest": {
  "preset": "jest-expo"
}

配置

¥Configuration

你可以使用的起始配置是确保在运行 Jest 时转换你在 node_modules 目录中使用的任何模块。这可以通过包含采用正则表达式模式作为其值的 transformIgnorePatterns 属性来完成:

¥A starting configuration you can use is to make sure any modules you are using within the node_modules directory are transpiled when running Jest. This can be done by including the transformIgnorePatterns property that takes a regex pattern as its value:

package.json
"jest": {
  "preset": "jest-expo",
  "transformIgnorePatterns": [
    "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)"
  ]
}
package.json
"jest": {
  "preset": "jest-expo",
  "transformIgnorePatterns": [
    "node_modules/(?!(?:.pnpm/)?((jest-)?react-native|@react-native(-community)?|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg))"
  ]
}

Jest 有多种配置选项。以上配置可以满足你的大部分需求。但是,你始终可以添加到此模式列表中。详细信息请参见 配置 Jest

¥Jest has various configuration options. The above configuration covers the majority of your needs. However, you can always add to this pattern list. For more details, see Configuring Jest.

单元测试

¥Unit test

单元测试用于检查最小的代码单元,通常是一个函数。

¥A unit test is used to check the smallest unit of code, usually a function.

要编写第一个单元测试,请首先为 App.js 编写一个简单的测试。为其创建一个测试文件并将其命名为 App.test.js。Jest 将扩展名为 .test.js 的文件识别为测试并将其包含在测试队列中。还有其他方法可以实现 构建测试

¥To write your first unit test, start by writing a simple test for App.js. Create a test file for it and call it App.test.js. Jest identifies a file with the .test.js extension as a test and includes it in the tests queue. There are also other ways to structure a test.

该测试预计 <App /> 组件的状态有一个子元素:

¥The test will expect the state of the <App /> component to have one child element:

App.test.js
import React from 'react';
import renderer from 'react-test-renderer';

import App from './App';

describe('<App />', () => {
  it('has 1 child', () => {
    const tree = renderer.create(<App />).toJSON();
    expect(tree.children.length).toBe(1);
  });
});
如果你使用的是 TypeScript,请使用 .ts 或 .tsx 文件扩展名。

运行测试:

¥To run the test:

Terminal
npm run test

如果一切顺利,你应该会看到一项测试已通过。欲了解更多信息,请参阅 期望和条件匹配器

¥If everything goes well, you should see the one test passed. For more information, see expect and conditional matchers.

构建你的测试

¥Structure your tests

现在,项目目录中有一个测试文件。添加更多测试文件可能会使组织项目目录变得困难。避免这种情况的最简单方法是创建一个 tests 目录并将所有测试放入其中。

¥Right now, you have a single test file in the project directory. Adding more test files can make it hard to organize your project directory. The easiest way to avoid this is to create a tests directory and put all your tests inside it.

示例结构如下所示:

¥An example structure is shown below:

__tests__
components
  button.test.js
navigation
  mainstack.test.js
screens
  home.test.js
src
components
  button.js
navigation
  mainstack.js
screens
  home.js

但是这种方式会导致很多长导入路径,比如 ../../src/components/button

¥However, this approach causes a lot of long import paths, such as ../../src/components/button.

或者,你可以为项目的不同区域设置多个 tests 子目录。例如,为组件、导航等创建单独的测试目录:

¥Alternatively, you can have multiple tests sub-directories for different areas of your project. For example, create a separate test directory for components, navigation, and so on:

src
components
  button.js
  __tests__
   button.test.js

现在,如果将 tests 移动到组件目录中,则 button.test.js 中 <Button> 的导入路径将是 ../button

¥Now, if you move tests within the components directory, the import path of <Button> in the the button.test.js will be ../button.

测试/文件结构的另一个选项:

¥Another option for test/file structure:

src
components
  button.js
  button.style.js
  button.test.js

这完全取决于偏好,并由你决定如何组织项目目录。

¥It's all about preferences and up to you to decide how you want to organize your project directory.

快照测试

¥Snapshot test

快照测试用于确保 UI 保持一致,尤其是当项目使用可能跨组件共享的全局样式时。欲了解更多信息,请参阅 快照测试

¥A snapshot test is used to make sure that UI stays consistent, especially when a project is working with global styles that are potentially shared across components. For more information, see snapshot testing.

要为 <App /> 添加快照测试,请在 App.test.js 中的 describe() 中添加以下代码片段:

¥To add a snapshot test for <App />, add the following code snippet in the describe() in App.test.js:

App.test.js
it('renders correctly', () => {
  const tree = renderer.create(<App />).toJSON();
  expect(tree).toMatchSnapshot();
});

运行 npm run test 命令,如果一切顺利,你应该看到创建的快照并通过了两个测试。

¥Run npm run test command, and if everything goes well, you should see a snapshot created and two tests passed.

代码覆盖率报告

¥Code coverage reports

代码覆盖率报告可以帮助你了解有多少代码经过了测试。

¥Code coverage reports can help you understand how much of your code is tested.

如果你想使用 HTML 格式查看项目中的代码覆盖率报告,请将以下内容添加到 package.json 中:

¥If you'd like to see code coverage report in your project using the HTML format, add the following to the package.json:

package.json
"jest": {
  ...
  "collectCoverage": true,
  "collectCoverageFrom": [
    "**/*.{js,jsx}",
    "!**/coverage/**",
    "!**/node_modules/**",
    "!**/babel.config.js",
    "!**/jest.setup.js"
  ]
}

添加上述代码片段允许 Jest 收集不在 coverage 或 node_modules 目录内的所有.js 和.jsx 文件的覆盖范围。它还排除 babel.config.js 和 jest.setup.js 文件。你可以在此列表中添加或删除更多内容以满足你的需求。

¥Adding the above snippet allows Jest to collect coverage of all .js and .jsx files that are not inside the coverage or node_modules directories. It also excludes the babel.config.js and jest.setup.js files. You can add or remove more to this list to match your needs.

运行 npm run test。你应该会看到在项目中创建了一个覆盖目录。在此目录中找到 index.html 文件,然后双击在浏览器中将其打开以查看覆盖率报告。

¥Run npm run test. You should see a coverage directory created in your project. Find the index.html file within this directory and double-click to open it up in a browser to see the coverage report.

通常,我们不建议将 index.html 文件上传到 git。为了防止它被跟踪,你可以在 .gitignore 文件中添加 coverage/**/*

¥Usually, we don't recommend uploading index.html file to git. To prevent it from being tracked, you can add coverage/**/* in the .gitignore file.

可选的:Jest 流

¥Optional: Jest flows

你还可以使用不同的流程来运行测试。以下是你可以尝试的一些示例脚本:

¥You can also use different flows to run your tests. Below are a few example scripts that you can try:

package.json
"scripts": {
  ...
  // active development of tests, watch files for changes and re-runs all tests
  "test": "jest --watch --coverage=false --changedSince=origin/main",

  // debug, console.logs and only re-runs the file that was changed
  "testDebug": "jest -o --watch --coverage=false",

  // displays code coverage in cli and updates the code coverage html
  "testFinal": "jest",

  // when a screen/component is updated, the test snapshots will throw an error, this updates them
  "updateSnapshots": "jest -u --coverage=false"
}

有关更多信息,请参阅 Jest 文档中的 CLI 选项

¥For more information, see CLI Options in Jest documentation.

更多

¥More

React Native 测试库

你还可以使用 React Native 测试库,它提供鼓励良好测试实践并与 Jest 配合使用的测试实用程序。

测试 Expo Router 的配置

了解如何在使用 Expo Router 时为你的应用创建集成测试。

Expo 中文网 - 粤ICP备13048890号