什么是前端测试

我们经常说的单元测试其实只是前端测试的一种。前端测试分为单元测试,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】点餐前端测试最佳实践