什么是前端测试

我们经常说的单元测试其实只是前端测试的一种。前端测试分为单元测试,UI 测试,集成测试和端到端测试。

  • 单元测试:是指对软件中的最小可测试单元进行检查和验证,通常指的是独立测试单个函数。
  • UI 测试:是对图形交互界面的测试。
  • 集成测试:就是测试应用中不同模块如何集成,如何一起工作,这和它的名字一致。
  • 端到端测试(e2e):是站在用户角度的测试,把我们的程序看成是一个黑盒子,我不懂你内部是怎么实现的,我只负责打开浏览器,把测试内容在页面上输入一遍,看是不是我想要得到的结果。

技术选型

前端测试的框架可谓是百花齐放。

  • 单元测试有 Mocha, Ava, Karma, Jest, Jasmine 等。
  • UI 测试有 ReactTestUtils, Test Render, Enzyme, React-Testing-Library, Vue-Test-Utils 等。
  • e2e 测试有 Nightwatch, Cypress, Phantomjs, Puppeteer 等。

单元测试

React 项目的技术选型和使用:

框架 断言 仿真 快照 异步测试 环境 并发测试 测试覆盖率
Mocha 默认不支持,可配置 默认不支持,可配置 默认不支持,可配置 友好 全局环境 否 需配置
Ava 默认支持 不支持,需第三方配置 默认支持 友好 隔离环境 是 不支持,需第三方配置
Jasmine 默认支持 默认支持 默认支持 不友好 全局环境 否 不需配置
Jest 默认支持 默认支持 默认支持 友好 隔离环境 是 不需配置
Karma 不支持,需第三方配置 不支持,需第三方配置 不支持,需第三方配置 不支持,需第三方配置 - - 需配置
  • Mocha 是生态最好,使用最广泛的单测框架,但是他需要较多的配置来实现它的高扩展性。
  • Ava 是更轻量高效简单的单测框架,但是自身不够稳定,并发运行文件多的时候会撑爆 CPU.
  • Jasmine 是单测框架的“元老”,开箱即用,但是异步测试支持较弱。
  • Jest 基于 Jasmine, 做了大量修改并添加了很多特性,同样开箱即用,但异步测试支持良好。
  • Karma 能在真实的浏览器中测试,强大适配器,可配置其他单测框架,一般会配合 Mocha 或 Jasmine 等一起使用。

每个框架都有自己的优缺点,没有最好的框架,只有最适合的框架。Augular 的默认测试框架就是 Karma + Jasmine,而 React 的默认测试框架是 Jest。

Jest 被各种 React 应用推荐和使用。它基于 Jasmine,至今已经做了大量修改并添加了很多特性,同样也是开箱即用,支持断言,仿真,快照等。Create React App 新建的项目就会默认配置 Jest,我们基本不用做太多改造,就可以直接使用。

UI 测试

UI 测试尽管有官方的测试框架 ReactTestUtils 和 Test Render,但是它们的 API 比较复杂,官方文档也是推荐使用 react-testing-library 或 Enzyme 这两个库。

Note: We recommend using React Testing Library which is designed to enable and encourage writing tests that use your components as the end users do. Alternatively, Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components’ output.

React Testing Library 和 Enzyme 都是基于 ReactTestUtils 和 Test Render,封装了更简洁易用的 API。

Enzyme 出来的更早,但是它常常会滞后于 React 功能的实现(大约半年左右,比如不支持 hooks,我不确定现在是否支持了)。React Testing Library 出的比较晚,但倾向于支持 React 的新功能,这对我来说在测试 Hooks 时是一个巨大的好处。

Enzyme 是从代码实现的角度出发进行测试,基于 state 和 props,而 React Testing Library 是从用户体验的角度出发,所以是基于 dom 进行测试。它也可能有更好的开发体验,以及更稳定的测试。这种方法使重构变得轻而易举,同时也可以实现可访问性的最佳实践。

当然因为 Enzyme 出的比较早,它的周围生态更好,很多大厂都用了它,不过也有一些正在做 迁移。我希望能够尝试更新更好的框架,所以最后选择了 React Testing Library.

e2e 测试

框架 是否跨浏览器支持 实现 优点 缺点
Nightwatch 是 Selenium 可以和其他框架一起使用。适用局部的功能测试场景 不支持 TypeScript, 社区文化稍弱于其他几个框架
Cypress 否 Chrome 容易调试和日志记录,使用 Mocha 作为它的测试结构,若单测使用的是 Mocha,所有测试使用的是相同的结构,看起来更“标准” 缺乏高级功能
Testcafe 是 Testcafe 支持TS,可并行测试,开箱即用 不支持录屏,DOM 快照等高级功能
Puppeteer 否 Chrome 速度快,易调试 Headless Chrome 不支持安装扩展

Puppeteer 是 Google Chrome 团队推出的库,尽管它相对其他 e2e 框架更新,但它同样也有一个庞大的社区。它拥有更简洁易用的 API,更快的运行速度,已逐渐成为业内自动化测试的标杆,俘获大量 Selenium 用户的心。可以看下近年来 e2e 测试框架的 npm trends。

前端测试学习笔记(一)前端测试概念和测试框架对比 - 图1

结论

对于 React 的项目的技术选型为 Jest + React Testing Library + Puppeteer
对于 Vue 的项目,为了保持技术栈的统一,选用了 Jest + Vue-Test-Utils + Puppeteer
**

编写原则

  • 测试代码时,只考虑测试,不考虑内部实现
  • 数据尽量模拟现实,越靠近现实越好
  • 充分考虑数据的边界条件
  • 对重点、复杂、核心代码,重点测试
  • 利用 AOP(beforeEach、afterEach),减少测试代码数量,避免无用功能
  • 测试、功能开发相结合,有利于设计和代码重构

编写说明

未来的项目都是基于 Talos 生成,其实也就是使用了 Create-React-App 生成 React 项目,使用了 Vue-CLI@3 生成了 Vue 项目。本身默认都有 Jest 的配置,不需做大的改动。

  • 单元测试和 UI 测试的文件夹统一命名为 tests,测试文件以 .test.js 为后缀
  • 将 tests 文件夹与它们正在测试的代码放在同级目录下,以便相对路径导入时路径更短
  • e2e 测试的文件夹命名为 e2e,并与 src 同放在根目录下
  • VScode 和 WebStorm 都有对应的 Jest 插件,安装后书写代码时有代码补全,debug 和自动运行等功能

**

参考

【1】点餐前端测试最佳实践