Jest, part 1: 什么是快照(snapshot)

December 26, 2019 ... ☕️ 5 min read

快照测试用以验证代码变动是否导致UI的异常,是否和预期相同。

它基于一个组件可测的前提:render必须为纯函数,所以在同样的条件下(包括state等),组件的输出内容(render)是一致的。

快照测试是什么

首先,快照测试区别于断言(assert)测试。断言常用非常准确的行为标准,例如toBeNull,准确判断某个位置输出是否为null。所以,断言可以保证app在一些场景下的的行为符合预期。断言要求场景严格可测,输出为确定的结果,并且不涉及逻辑变更的代码变动,通常不影响测试结果。

而快照测试,是以某次稳定版本为基准,建立一张快照,以后的所有代码修改相关测试,都会以此为基准进行。直到确认并进行update来更新基准快照,然后重复该过程。快照不要求有明确的输出结果,只要代码造成输出结果变动,快照测试就不通过。

举个例子

有一个modal组件,首先执行一次snapshot测试。然后,我们为它的一个元素添加了’modal-test’的class,然后执行快照测试,输出结果这样:

snapshot-test

上图中,导致输出的快照产生差异变化,jest会以+-标记出变更内容。当产生意料之外的更改时(如此变更导致文件b的输出也收到影响),可以及时发现。

快照测试的适用范围

快照测试对于一些经常变更,但是不太好规划断言测试用例的场景比较合适。

举个例子,上例中修改了组件的样式名、或者添加了一层样式包装。单独写一个或几个测试用例来针对这项改动,显然会增加代码量,拖慢开发进度。而且经常的变更,会导致代码激增,测试结果也会很乱(比如“验证是否包含xx样式”,“验证是否有父级div”)且无意义。

但是如果只看快照,就会很简单,这些改动都会被标记出来,只需简单验证一下,执行update来接受(或者回退)这些变更即可。

缺点

快照测试的基础要求,在于测试用例覆盖程度必须相当高,才能发挥功能。为什么呢?项目开发初期,UI会大幅度调整,逻辑也会经常变更,还未达到验收标准,这时看快照显然是不合适的。

所以必须需要经过长时间迭代之后,快照才能趋于稳定。

另外,由于它只是基于“快照”,并没有像断言测试一样,有明确的正确/错误判断标准。所以它不会提示代码逻辑错误或遗漏,所以用来标示测试用例覆盖程度也意义不大。

理想的的使用场景

工程经过一次或几次上线,达到稳定状态。此时需要:

1、react-native等编译时间较长的场景下,希望快速查看修改结果

react-native需要一些编译时间,一些情况下需要用手机查看,(甩一甩)耗时间,(注意力转移)不方便。直接在命令行查看snapshot,修改组件状态,即可查看结构是否符合预期。

2、UI、组件更新

同时由于数次补丁,可能存在大规模复用的UI组件。当修改了一些样式、props属性,可能引起其他地方(预料之外)的变更。

还是拿modal举例,给某个复用的弹窗添加了新的类型

single-btn

新增了两个按钮的样式

two-btn

此时就需要检查变更是否会引起其他异常。比如:之前单按钮的地方,传入的props是否需要更改?会不会导致输出变化?

此时,进行代码重构是必要的,而快照测试是一个不错的辅助方法。

#jest