首页指南参考教程

使用 Jest 进行单元测试

了解如何设置和配置 jest-expo 库以使用 Jest 为项目编写单元和快照测试。


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

¥Jest is the most widely used unit and snapshot JavaScript testing framework. In this guide, you will 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 的原生部分并处理 Expo 项目所需的大部分配置。

¥You will also use the jest-expo library, which is a Jest preset that mocks the native part of the Expo SDK and handles most of the configuration required for your Expo project.

安装和配置

¥Installation and configuration

如果你使用 默认 Expo 模板 创建了项目,则可以跳过此部分。jest-expo 和其他所需的开发依赖已安装并配置。

¥If you have created your project using the default Expo template, you can skip this section. The jest-expo and other required dev dependencies are already installed and configured.

Manual installation instructions for jest-expo

如果你使用 不同的模板 创建了项目,请按照以下说明在你的项目中安装和配置 jest-expo

¥If you have created your project using different template, follow the instructions below to install and configure jest-expo in your project.

1

在你的项目中安装 jest-expo 和其他所需的开发依赖。从项目的根目录运行以下命令:

¥Install jest-expo and other required dev dependencies in your project. Run the following command from your project's root directory:

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

# For yarn
yarn add -D jest-expo jest @types/jest

注意:如果你的项目未使用 TypeScript,则可以跳过安装 @types/jest

¥Note: If your project is not using TypeScript, you can skip installing @types/jest.

2

打开 package.json,添加一个用于运行测试的脚本,并添加使用来自 jest-expo 的基本配置的预设:

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

package.json
{
  "scripts": {
    "test": "jest --watchAll"
    %%placeholder-start%%... %%placeholder-end%%},
  "jest": {
    "preset": "jest-expo"
  }
}
Additional configuration for using transformIgnorePatterns

你可以通过在 package.json 中配置 transformIgnorePatterns 来转换项目使用的节点模块。此属性以正则表达式模式作为其值:

¥You can transpile node modules your project uses by configuring transformIgnorePatterns in your package.json. This property 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/.*|@sentry/react-native|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/.*|@sentry/react-native|native-base|react-native-svg))"
  ]
}

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

¥Jest has many configuration options, but the above configuration should cover most of your needs. However, you can always add to this pattern list. For more details, see Configuring Jest.

安装 React Native 测试库

¥Install React Native Testing Library

React Native 测试库 (@testing-library/react-native) 是用于测试 React Native 组件的轻量级解决方案。它提供实用功能并与 Jest 配合使用。

¥The React Native Testing Library (@testing-library/react-native) is a lightweight solution for testing React Native components. It provides utility functions and works with Jest.

要安装它,请运行以下命令:

¥To install it, run the following command:

Terminal
# For all other package managers
npx expo install -- --save-dev @testing-library/react-native

# For yarn
yarn add -D @testing-library/react-native
已弃用:如果你使用的是默认的 Expo 模板,则在安装此库后,你可以从项目的开发依赖中卸载 react-test-renderer@types/react-test-rendererreact-test-renderer 已被弃用,将来将不再维护。参见 有关更多信息,请参阅 React 的文档

单元测试

¥Unit test

单元测试检查最小的代码单元,通常是一个函数。要编写第一个单元测试,请查看以下示例:

¥A unit test checks the smallest unit of code, usually a function. To write your first unit test, take a look at the following example:

1

在项目的 app 目录中,创建一个名为 index.tsx 的新文件,以及以下代码来渲染一个简单的组件:

¥Inside the app directory of your project, create a new file called index.tsx, and the following code to render a simple component:

index.tsx
import { PropsWithChildren } from 'react';
import { StyleSheet, Text, View } from 'react-native';

export const CustomText = ({ children }: PropsWithChildren) => <Text>{children}</Text>;

export default function HomeScreen() {
  return (
    <View style={styles.container}>
      <CustomText>Welcome!</CustomText>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

2

在项目目录的根目录下创建一个 tests 目录。如果此目录已存在于你的项目中,请使用该目录。然后,创建一个名为 HomeScreen-test.tsx 的新文件。jest-expo 预设自定义 Jest 配置,以将带有 -test.ts|tsx 扩展名的文件标识为测试。

¥Create a tests directory at the root of your project's directory. If this directory already exists in your project, use that. Then, create a new file called HomeScreen-test.tsx. The jest-expo preset customizes the Jest configuration to also identify files with -test.ts|tsx extensions as tests.

在 HomeScreen-test.tsx 中添加以下示例代码:

¥Add the following example code in HomeScreen-test.tsx:

HomeScreen-test.tsx
import { render } from '@testing-library/react-native';

import HomeScreen, { CustomText } from '@/app/index';

describe('<HomeScreen />', () => {
  test('Text renders correctly on HomeScreen', () => {
    const { getByText } = render(<HomeScreen />);

    const textLabel = getByText('Welcome!');

    expect(textLabel).toBeTruthy();
  });
});

在上面的例子中,getByText 查询可帮助你的测试在应用的用户界面中找到相关元素。React Native 测试库提供此查询。欲了解更多信息,请参阅 所需的 iOS 应用凭据

¥In the above example, the getByText query helps your tests find relevant elements in your app's user interface. The React Native Testing Library provides this query. For more information, see querying with React Native Testing Library.

此示例还使用了 Jest 提供的条件匹配器 expect,,可帮助你验证查询的元素是否与预期值匹配。欲了解更多信息,请参阅 expect 和条件匹配器

¥This example also uses expect, a conditional matcher provided by Jest that helps you verify that the element you are querying matches the expected value. For more information, see expect and conditional matchers.

3

在终端窗口中运行以下命令以执行测试:

¥Run the following command in a terminal window to execute the test:

Terminal
npm run test

你将看到一个测试通过。

¥You will see one test being passed.

构建你的测试

¥Structure your tests

组织测试文件对于使它们更易于维护非常重要。一种常见的模式是创建一个 tests 目录并将所有测试放入其中。

¥Organizing your test files is important to make them easier to maintain. A common pattern is creating a tests directory and putting all your tests inside.

组件目录旁边的测试示例结构如下所示:

¥An example structure of tests next to the components directory is shown below:

__tests__
ThemedText-test.tsx
components
ThemedText.tsx
ThemedView.tsx

或者,你可以为项目的不同区域设置多个 tests 子目录。例如,为组件创建一个单独的测试目录,依此类推:

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

components
ThemedText.tsx
__tests__
  ThemedText-test.tsx
utils
index.tsx
__tests__
  index-test.tsx

这完全取决于偏好,你可以自行决定如何组织项目目录。

¥It's all about preferences, and it is 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.

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

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

HomeScreen-test.tsx
describe('<HomeScreen />', () => {
  %%placeholder-start%%... %%placeholder-end%%

  test('CustomText renders correctly', () => {
    const tree = render(<CustomText>Some text</CustomText>).toJSON();

    expect(tree).toMatchSnapshot();
  });
});

运行 npm run test 命令,你将看到在 testssnapshots 目录中创建了一个快照,并且通过了两个测试。

¥Run npm run test command, and you will see a snapshot created inside tests_snapshots_ directory, and two tests passed.

代码覆盖率报告

¥Code coverage reports

代码覆盖率报告可以帮助你了解有多少代码经过了测试。要使用 HTML 格式查看项目中的代码覆盖率报告,请在 package.json 中的 jest 下,将 collectCoverage 设置为 true,并使用 collectCoverageFrom 指定收集覆盖率时要忽略的文件列表。

¥Code coverage reports can help you understand how much of your code is tested. To see the code coverage report in your project using the HTML format, in package.json, under jest, set the collectCoverage to true and use collectCoverageFrom to specify a list of files to ignore when collecting the coverage.

package.json
"jest": {
  ...
  "collectCoverage": true,
  "collectCoverageFrom": [
    "**/*.{ts,tsx,js,jsx}",
    "!**/coverage/**",
    "!**/node_modules/**",
    "!**/babel.config.js",
    "!**/expo-env.d.ts",
    "!**/.expo/**"
  ]
}

运行 npm run test。你将看到在你的项目中创建的覆盖目录。找到 lcov-report/index.html 并在浏览器中打开它以查看覆盖率报告。

¥Run npm run test. You will see a coverage directory created in your project. Find the lcov-report/index.html and open it in a browser to see the coverage report.

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

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

Jest 流程(可选)

¥Jest flows (optional)

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

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

package.json
"scripts": {
  "test": "jest --watch --coverage=false --changedSince=origin/main",
  "testDebug": "jest -o --watch --coverage=false",
  "testFinal": "jest",
  "updateSnapshots": "jest -u --coverage=false"
  %%placeholder-start%%... %%placeholder-end%%
}

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

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

附加信息

¥Additional information

React Native 测试库文档

请参阅 React Native Testing Library 文档,该文档提供测试实用程序并鼓励良好的测试实践和使用 Jest。

测试 Expo Router 的配置

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

使用 EAS Build 和 Maestro 进行 E2E 测试

了解如何使用 Maestro 在 EAS Build 上设置和运行 E2E 测试。

Expo 中文网 - 粤ICP备13048890号