在Jest中创建快照以测试React应用程序

556 阅读9分钟

本教程包括。

  1. 设置Jest快照
  2. 使用快照来模拟测试的UI变化
  3. 使用快照测试来确定变化是否是故意的

自动测试在有很多移动部件的大型应用程序中特别重要。了解许多测试应用程序的方法是明智的,这样你就可以提供尽可能多的覆盖。如果你不熟悉在测试中使用快照,请继续阅读。快照测试是作为前端测试自动化的一部分编写的。

在本教程中,我将带领你使用Jest,一个JavaScript测试框架,为测试一个简单的ReactWeb应用程序创建快照。使用Jest快照将帮助你确保你的UI变化是确定的,并且你能知道什么时候发生了变化。利用这些信息,你可以确定这些变化是否是故意的。我们将使用用Jest创建的快照来模拟React应用中的变化。如果不断变化的文本断言是痛苦的,你可能会发现快照测试是一种强大的解药。

前提条件

要跟上本教程,你需要以下条件。

  • 本地安装的NodeJS
  • 一个GitHub账户。
  • 一个CircleCI账户。
  • 有关JavaScript、React、Git和Jest的基本知识。

我们的教程是与平台无关的,但使用CircleCI作为一个例子。如果你没有CircleCI账户,请**在这里注册一个免费账户。**

Jest中的快照测试

Jest是一个JavaScript测试框架,它使编写前端测试如快照、单元测试和组件测试变得简单而高效。快照测试是输出比较测试的一种类型。这种类型的测试确保你的应用程序坚持你的开发团队的质量特征和代码价值。

快照测试如何工作

当你想确保你的用户界面不发生意外变化时,快照测试是很有用的。一个典型的快照测试案例会渲染一个UI组件,拍摄一个快照,然后将其与存储在测试旁边的参考快照文件进行比较。该测试将您的应用程序的当前状态与建立的快照和预期行为进行比较。

快照测试过程的可视化

下面的图片说明了Jest中的快照测试过程。它显示了快照通过时、失败时的不同结果,以及发生的动作。

Snapshot testing

设置React应用程序的样本

在本教程中,我们的应用程序将由一个简单的React组件组成,该组件有两个按钮,当点击时可以增加和减少计数。

在你的终端运行这个命令来克隆资源库。

git clone https://github.com:mwaz/jest-snapshot-testing.git;

cd jest-snapshot-testing;

接下来,你需要从npmReact测试库JestReact测试渲染器中安装以下依赖项。

它们被安装在我们的package.json 文件中。要在你的系统中安装它们,打开你的终端并运行。

npm install

一旦依赖关系安装完毕,使用这个命令运行应用程序。

npm start

这将启动你的应用程序。

Jest test application

我们的测试将确定计数器的值是否初始化为零,以及按钮是否工作。因为值的变化取决于被点击的按钮,你可能想知道增量或减量的值保持不变,总是增加或减少1。现在你可以开始编写你的测试了。

编写快照测试

Jest使用正则表达式来寻找带有.test.js.test.jsx 扩展名的文件。一旦遇到具有这些扩展名的测试文件,Jest将在执行测试命令时自动运行这些文件中的测试。

为了编写你的第一个快照测试,你将使用renderer 模块。这个模块渲染了将被保存为文本快照的文档对象模型(DOM)元素。

import renderer from "react-test-renderer";

编写你的测试,以确保它捕捉到<App> 组件的渲染,并将其保存为Jest快照。这就是测试的结构。

import React from "react";
import renderer from "react-test-renderer";
import App from "./App";

describe("Jest Snapshot testing suite", () => {
  it("Matches DOM Snapshot", () => {
    const domTree = renderer.create(<App />).toJSON();
    expect(tree).toMatchSnapshot();
  });
});

该测试有domTree 变量,它持有JSON格式的已渲染组件的DOM树。这使得保存和比较快照更加容易。如果不存在快照,expect(domTree).toMatchSnapshot() 创建一个快照,保存它,并检查快照是否与以前存储的快照一致。如果有一个现有的快照,Jest会比较这两个快照。如果它们匹配,则测试通过。不匹配的快照会导致测试失败。该测试还使用.toJSON() 方法,该方法返回一个渲染的DOM树快照的JSON对象。

一旦你运行了这个测试(使用命令npm test ),会有一个新的文件夹叫做(__snapshots__) ,里面有一个文件App.test.js.snap 。该文件包含了保存的快照,它应该类似于这个片段。

exports[`Jest Snapshot testing suite matches snapshot 1`] = `
<div
  className="App"
>
  <div
    className="counter"
  >
    <div
      className="buttons"
    >
      <button
        onClick={[Function]}
      >
        Increment
      </button>
      <button
        onClick={[Function]}
      >
        Decrement
      </button>
    </div>
    <p>
      0
    </p>
  </div>
</div>
`;

这个快照文件显示了该组件的DOM树的样子,包括父选择器元素和子元素。

为了更好地理解快照,在你的React应用程序运行的标签中打开elements 部分。将其与快照并排比较;它们应该几乎是相同的。快照有一个类似于DOM的结构,这使得识别DOM变化的过程变得无缝。

Application DOM structure

文本快照是从DOM中创建的,这意味着只有当DOM发生变化或者内容与拍摄快照时的内容不同时,它们才会失效。接下来,我们将研究DOM中的变化如何发生,如何触发快照变化,以及如何处理这一过程。

处理快照变化

现在你知道了快照是如何被创建的,现在是时候了解更多关于快照失败的时间和原因了。为了证明这一点,我们将使用上述测试并对我们的DOM树进行修改。我们要做的改变是给组件引入一个标题<h1>COUNTER</h1> 。这个添加的内容显示在文件Counter.js

return (
      <div className="counter">
        <h1>COUNTER</h1>
        <div className="buttons">
          <button onClick={this.increment}>Increment</button>
          <button onClick={this.decrement}>Decrement</button>
        </div>
        <p>{this.state.count}</p>
      </div>
    );

做完这个改动后,再次运行测试。测试应该失败。

Failed snapshot

因为这些变化是预期的,你将需要更新你现有的快照,而不是改变代码来匹配以前的快照。当Jest在watch mode ,选择u选项来更新快照。更新快照告诉Jest,这些变化是故意的,而且你想保留。在快照更新被触发后,你的测试又回到了快乐的状态,并且漂亮地通过了。

注意。 当Jest在watch mode ,应用程序被跟踪,所以任何变化都会触发测试的重新运行。要激活watch mode ,在Jest运行中用--watch 参数指定它。

 PASS  src/App.test.js (20.905 s)
  Jest Snapshot testing suite
    √ Matches Snapshot (64 ms)

 > 1 snapshot updated.
Snapshot Summary
 > 1 snapshot updated from 1 test suite.
   ↳ src/App.test.js

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 updated, 1 total
Time:        51.348 s
Ran all test suites related to changed files.

添加更多快照测试

你可以添加更多的快照测试,以确保你的应用程序中所有重要的视觉元素与你的UI规范和用户体验指南相一致,并确保你的应用程序中的一切都能正常工作。快照测试是全面的前端测试的一部分,还应该包括单元和组件测试。

在本教程中,我将通过添加一个快照测试来运行。这个测试检查增量功能是否按预期工作。这个代码片段可以在文件App.test.js 中找到。

it("Should render 3 after three increments", () => {
    const component = renderer.create(<Counter />);
    component.getInstance().increment();
    component.getInstance().increment();
    component.getInstance().increment();
    expect(component.toJSON()).toMatchSnapshot();
});

在这个测试中,计数器组件结构被保存到一个组件变量中。然后测试访问我们的class-based componentincrement() 方法,并调用它三次。目的是确保当Increment 按钮被点击三次时,所呈现的计数是三。这个信息被保存到快照中,它应该是通过的。

将快照测试与CircleCI结合起来

一位智者(我自己)曾经问道。"为什么要运行别人不知道的成功测试?"花点时间与团队的其他成员分享你的测试,这样他们也可以从他们提供的洞察力中受益。

在本教程中,我将带领你完成使用CircleCI执行快照测试的步骤。

在你的应用程序的根文件夹中,创建一个.circleci 文件夹,并添加一个config.yml 文件。该文件将包含运行你的CircleCI管道所需的所有配置。

在CircleCI config.yml文件中,添加这个配置。

version: 2.1
jobs:
  build:
    working_directory: ~/repo
    docker:
      - image: cimg/node:14.17.1
    steps:
      - checkout
      - restore_cache:
          key: dependency-cache-{{ checksum "package-lock.json" }}
      - run:
          name: install dependencies
          command: npm install
      - save_cache:
          key: dependency-cache-{{ checksum "package-lock.json" }}
          paths:
            - ./node_modules
      - run:
          name: Jest snapshot tests
          command: npm test
      - store_artifacts:
          path: ~/repo/jest-snapshot-testing

将你的修改推送到GitHub

如果你克隆了仓库,变化已经存在,使这一步骤成为一个选项。然而,如果你使用不同的仓库,并使用相同的配置,你将需要推送变化到仓库。

保存这个文件,提交并推送你的变化到你的GitHub仓库。导航到CircleCI仪表板后,点击仓库名称旁边的Set up Project

当出现提示时,选择main ,这是我们的默认分支。然后点击Set Up Project。你的项目将开始在CircleCI上运行。

CircleCI branch configuration

在CircleCI的仪表板上应该有一个绿色的构建。点击查看构建细节。

Successful build

太棒了!我们的构建是绿色的,所有的测试都成功执行。

总结

在本教程中,你已经了解了快照测试,以及它在确保你的用户界面看起来和工作时是多么有用。你学会了如何编写快照测试,并使用快照作为比较,以确保所做的任何改变都是预期的。你还学会了如何更新快照,以防出现有意的变化。最后,你整合了CircleCI来运行你的测试。我希望你喜欢这个教程的项目工作。直到下一次,继续编码


Waweru Mwaura是一名软件工程师和终身学习者,专门从事质量工程。他是Packt的一名作者,喜欢阅读关于工程、金融和技术的文章。你可以在他的网站简介中了解更多关于他的信息。