≈
最近把组件测试接入到日常开发,提高了项目代码健壮性,可维护性。本人也从0到1收获了组件测试的经验。
本文总结一下最近两周 组件测试 相关的研究,包括:
Jest 是一套Facebook家背书的测试框架。
实际上,编写一个测试用例,我们需要以下准备:
Jest是包含以上(1234)四合一的一款测试框架。
当然Jest也有一些劣势。
2019年另一款很火的测试框架Mocha,自身不带断言库,也不带Func/Module Mock,集成社区相对成熟的断言库Chai和mock库SinonJS之后,非常强大。Chai断言库相较于Jest内置的断言库API更加丰富更加强大,SinonJS的mock的API也十分完善。而且Mocha的不带其他杂七杂八功能的理念,让它十分具有可配置性。
但是最终选择Jest原因有以下几点:
1. 没有最牛逼的框架,只有最合适的框架。
2. 更简单的配置,更快地上手。
3. 实际上Jest的可配置化也非常强。
4. MVVM框架支持度
Enzyme是Airbnb家的React组件用例测试渲染库。
实际上React官方对于React components的测试有暴露一些库:
react-dom/test-utils
: 拥有一些看一遍也不知道怎么用的API。react-test-render
:可以无渲染环境的基础下,通过shallow渲染拿到WHATWG规范的DOM树结构。React团队利用这个库和Jest团队一起努力打造了React的snapshot test。Enzyme底层就是封装了以上两个库,却拥有简单精巧的API,打败了React家自带的test render(API设计的力量!React家也一直在安利Enzyme…)。它一共有三个大API:
react-test-render/shallow
,生成的是虚拟DOM。Enzyme对于以上三种渲染方式都有详细介绍的小API查询。
最终选择Enzyme原因很明确了,这是目前为止最简单上手,功能最强大的React components render库了。
Jest一些十分有用的Config:
Jest实际上可以测试任意文件:只要你的文件可以通过transform,得到的结果可以被Jest的断言库语法解析。因此一个Markdown,txt等等文件都可以被测试。
Jest默认会mock所有node_modules目录下的依赖文件。我们既可以在config配置文件中配置全局mock规则,也可以在测试用例编写的时候mock某一个function或module。
Jest在内部是这样处理的:拿到file code之后,包一层函数,传入重写的require,export函数。把mock的代码接在code前面。然后一起执行?。
Jest一共有30多个package,从零开始看你会疯掉。如果想要研究的话,推荐看去年底,Jest官方发布的架构原理视频:https://jestjs.io/docs/en/architecture, 粗略地讲了其中几个重要的包的功能,以及一个测试用例如何被初始化,添加Mock,调度,最终执行的过程。核心内容就是下面这张图。
Jest本身其实是基于Jasmine库之上封装的,Jest的断言库和具体的测试用例执行过程都是Jasmine做的。Jest本身做的是以下事情:
(现在还会出现栈溢出的问题,对此Jest的做法是加一个100ms的timeout解决我的天。我在用Jest的时候,snapshot稳稳栈溢出,需要加一个enzyme-to-json/serializer
解决。
Jasmine是BDD(behavior-driven development行为驱动开发)的Javascript测试框架。Jasmine非常轻量,本身只有20KB。Jest目前的断言语法都是来自于Jasmine。它定义有如下两种语法:
以下是一段测试用例代码:
describe("A suite", function() {
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});});
非常语义化,不用看API都能看懂,类似Regular English,这就是BDD。
它拿到用户配置,首先会正则匹配到所有符合要求的文件,抽取出一颗树processTree,因为它支持Suite的嵌套,所以它会先遍历这棵树,做一次order更新,然后用捕获冒泡的方式从树根遍历到树叶再从树叶的father节点再遍历到树根,在它的context下执行测试用例。目的是把测试report通知到所有祖先Suite,最后打出一份Report。(但是,你不要以为Jasmine体积小就好阅读了,Jasmine的源码就是一坨回调地狱。我认为它可以选择重构。)
Jest独立出来的其中一个包,就是图中所说的jest-circus。我们可以通过配置选择circus而不是jasmine, 它将要替代Jasmine???
Circus is a flux-based test runner for Jest that is fast, easy to maintain, and simple to extend.
官方说Circus更加快,好维护,易拓展。它支持用户接入任何自定义的执行环境。
import {NodeEnvironment} from 'jest-environment-node';
import {Event, State} from 'jest-circus';
// 自定义的环境
class MyCustomEnvironment extends NodeEnvironment {
//...
handleTestEvent(event: Event, state: State) {
if (event.name === 'test_start') {
// ...
}
}
}
它使用了Flux的思想,自己维护了一个state,然后通过事件的Emitter去更新state,没有回调地狱的存在。所以它说:
Mutating event or state data is currently unsupported and may cause unexpected behavior or break in a future release without warning. New events, event data, and/or state data will not be considered a breaking change and may be added in any minor release.
它只支持不可变数据和函数。
Jest有自己的平台https://jestjs.io/docs/en/jest-platform,提供了一些工具函数。
未来的话,Jest有倾向: