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