在真正了解到jest和enzyme之前,选择jest作为我react项目的测试框架,仅仅从以下几个方面:
- facebook开发,他们自己在用,经得起考验,质量有保障
- 社区活跃,出了问题应该容易找解决方案
- antd用的也是这个,这样我可以参考一下人家怎么写的: 后来发现是antd的测试基本只是snapshot这方面的。。。
但是了解和使用jest+enzyme之后,从未接触过测试相关知识的我仿佛打开了新世界的大门~
jest
jest 作为一款测试框架,拥有测试框架该有的一套体系,丰富的断言库,大多数api与老牌的测试框架如jasmine、mocha,譬如常用的expect、test(it)、toBe等,都非常好用。内部也是使用了jasmine作为基础,在其上封装。但是因为Snapshot这个特色功能,非常适合react项目的测试。
特色
-
Snapshot组件快照
借用
react-test-renderer
库的renderer
获得react组件渲染成的React树,调用toJSON接口格式化,在使用jest
的expect(tree).toMatchSnapshot()
将快照与上一次的快照作对比,首次生成的某个测试案例的快照将会被保存下来,以后每次运行时都会与上一次对比,如果发现不匹配会抛出错误,需要自己去查看差异是否是合法的需要更新的内容。这种方式对比react组件渲染后的内容,在静态ui上,非常高效的找出差别,维护稳定性。
-
多线程同时跑测试案例,速度快
这个我观察了一下我写的不多的几个测试,5个测试脚本一起跑和只跑1个时间基本相同,5s左右,环境初始化还是挺慢的,看单个脚本的分析,每个测试单元都只耗了几百毫秒,环境的初始化时秒级别的。但是确实是多线程同时跑速度大大提升。
-
可配置的coverage reports
生成测试覆盖报告无需再下其他依赖,已被内置,
jest --coverage
就能生成coverage文件夹保存,方便分析。形如: -
强大的mocking库
可以mock值、函数、文件多种类型
- mock函数:mock的函数可以被追踪到,`const handler = jest.fn()`,譬如后续可以通过`expect(handler).toBeCalled()`检查mock的函数是否如期被调用,`expect(handler).toBeCalledWith('arg')`检查mock的函数是否调用时传入的参数是`arg`等。
- mock文件:诸如css、image等于逻辑测试无关的资源文件可以在配置时就被mock掉`"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/spec/__mocks__/fileMock.js",
"\\.(css|scss)$": "<rootDir>/spec/__mocks__/styleMock.js",`,这样`import`时就不会真的去引入这些无用的文件了。
- time mock:`setTimeout, setInterval, clearTimeout, clearInterval`默认是被mock的,这样就不会再执行是真的等待这些函数获取的时间参数,影响测试执行速度了,但是内部特殊的mock让其依旧能保证异步进行和执行顺序。
-
内置jsdom,提供了dom依存的环境
jest 配合enzyme,enzyme可以在jsDom里渲染出虚拟dom,然后我们可以操作它,进行交互测试。依旧有window、document等对象,但是无法往这个dom中插入script标签进行其他资源文件的加载。
enzyme
enzyme提供了几种方式中将react组件渲染成真实的dom,提供了类似jquery的api来获取dom;提供了simulate函数来模拟事件触发;提供接口让我们获取到组件的state和props并且能对其进行操作。
enzyme其实是react-test-renderer
的封装,react-test-renderer
的api非常不友好,但是enzyme开发的api跟jquery一致。如:
还可以接入enzyme-to-json
,这样在将enzyme生成的react树生成snapshot时就可以使用toJson
进行格式化,提高生成的snapshot的可读性,代替了react-test-renderer
的toJSON
接口。