【React总结(三)】React 组件自动化测试与持续集成指北(1)
? 导语
本文主要介绍基于 React 框架的项目,在对自己封装组件或者是通过 HOC , render props 的方式在第三方 UI 组件库(e.g. Ant Design)的基础上封装的公共组件的自动化测试技术选型以及在项目中的实践
?封装组件的背景
在多人协作的项目中,特别是项目团队中,会有多个技术选型类似的项目,例如是都是通过 React 全家桶搭建的项目。随着项目的业务逻辑逐渐增加,我们都会抽取其中一些公共的代码,特别是一些与业务没有强耦合的组件,组成一个基础公共组件库,提供给各个项目使用。听起来很美好,但是在实际工程实践方面,会产生一些问题:
如何保组件库的质量?如何确保修改更新不会影响其他的项目?如何最快地回归测试?
?技术选型
为了解决上面的问题,我们自然就会想到,其实我们需要一个自动化测试,我们在项目中的选型是这样的:
- Jest: Jest是一个令人愉快的 JavaScript 测试框架,专注于简单性。
- enzyme: Enzyme 是 React 的 JavaScript 测试实用程序,可以更轻松地测试 React Components 的输出。您还可以在给定输出的情况下操纵,遍历并以某种方式模拟运行时。
- CI: 接入 CI 实现真正的自动化测试。
? 找出自动化测试中需要测试的部分
假设你们多个项目都在使用一个叫做 Component
的公共组件库,你现在需要通过通过测试的方式来保证这个库能在各个项目中稳定运行。你应该怎么样着手开始做这个事情? 做到 coverage
100%就可以了吗?当然这是我们一直追求的目标,但是,在绝大多是的情况下,我们并不需要完全覆盖所有的代码?
为什么呢? 其实我们都知道,即使我们真的覆盖了 100% 的代码,也没有办法保证该组件是没有bug的。所以不要为了追求代码覆盖率达到 100% 而写一些无意义的测试用例,但是要尽量覆盖了组件的主要逻辑。
所以哪些代码是我们在测试用例中不用覆盖的
- 第三方库: 不需要去测试第三方库,例如你的组件当引用了 Antd 的一个
<Input />
组件,在你写测试用例的时候你应该跳过这个组件,因为你不对这个组件负责,并且选用第三方库的时候,应该留意这个第三方库的测试用例是否全面的,因为这直接可以判断这个第三方库是否可靠的。 - 常量: 一旦常量被定义,他们不应该是经常改变的,可以把他们理解为一个静态的代码集,无需加入到组件的测试用例中。
- 内联样式: 为了测试内联样式,需要使用测试中的样式复制对象。如果对象样式更改,则必须在测试中也更改它们。记住一条不要在测试用例中复制组件的代码。你经常会忘记在测试中更改它。而且,你的同事永远不会意思到改个样式还要改测试用例。在大多数情况下,内联样式不会改变组件的行为,因此不需要对它们进行测试。如果样式是动态更改的,这时候才需要加入到测试用例中。
- 其他: 跳过覆盖在测试组件中导入的测试组件。 如果它是包裹在另一个组件中的组件。不要测试包装器,只需单独分析和测试内部独立的组件即可。
下面来聊一下如何写测试用例,我总结分为两个方法:
- Snapshot 快照测试
- 组件业务逻辑测试
建议阅读下面内容之前,先了解一下 Enzyme 的基本 api: https://github.com/airbnb/enzyme
? 通过 Snapshot 进行测试
Snapshot 是一个很有用的测试工具,它让我们可以在第一时间在用户界面这个层级上知道页面是否被修改。而且他用起来非常简单。
步骤 1. 在写组件测试的时候,使用 .toMatchSnapshot()
创建一个 snapshot 快照,
describe('Input', () => {
it('render correctly Input component', () => {
const InputComponent = renderer.create(<Input />).toJSON();
expect(InputComponent).toMatchSnapshot();
});
}
步骤 2. 当你首次运行这个 test 的时候,在测试过程中, 会生成一个 __snapshots__
的文件夹,里面的文件就是我们生成的快照,
步骤 3. 把这个 __snapshots__
的文件夹提交到你的代码仓库,如果组件有更新的时候,只需要跑 test 命令的时候带上-updateSnapshot
选项即可。
当组件发生变更的时候
如果组件发生了变更,到那时没有生成新的 snapshot ,那么当跑 npm test
的时候,新的 __snapshots__
文件夹会被生成,并且 test 不会通过,因为这次的 snapshot 和之前的不匹配。
当组件没有变更的时候
npm test
的测试是通过的,因为 snapshot 是匹配的。
如果你要测试的组件仅仅是一个很简单的 UI 组件,那么你可以直接通过 snapshot 来测试,而不用测试其中的逻辑。
但是这对于复杂的组件来说,是完全不够的,因此,我们还需要测试组件的逻辑。
⚙️如何测试组件的逻辑
1、创建一个 snapshot
一个需要被测试的组件往往只需要创建一个 snapchat,具体的使用方法可以像上面的说明一样操作,没必要创建多个 snapshot。
2、测试 props
测试 props 主要分为两步走:
- 首先是先传入一个默认值,或者是不传值,看组件是否正常通过
defaultProps
进行组件的渲染。 - 然后再通过
setProps
的方式设置组件的 props,测试其 props 是否正常渲染我需要的东西。
3、模拟事件的触发来测试组件
通过 snapshot 测试和 props 测试,已经能确保组件是可以正常渲染的了,但是这还远远不够,因为有很多分支代码我们是没有覆盖到的,如果你查看 jest --coverage
, 你会发现还有很多触发事件的函数没有被覆盖,所以这里我们需要模拟一些事件测试。
通常来说比较常用的3个测试事件的方案是:
- mock 一个事件 ➡️ simulate 一个事件 ➡️ 断言这个事件被调用
- mock 一个事件 ➡️ 带参 simulate 一个事件 ➡️ 断言这个事件被调用,并且接收到参数
- 传递props进去组件 ➡️ render 这个组件 ➡️ simulate 一个事件 ➡️断言一个当事件被调用的时候的行为
4、测试 state
如果要测试 state,那么需要写两个测试用例
- 首先先测试当前 state 的表现是否正常
- 然后通过模拟事件 ➡️触发组件内的 state 发生变化 ➡️检查 state 变化后是否正常渲染出期待的内容。(通过组件的实例可以调用组件内部的方法)
当你按照前面 4 个步骤写下来,基本上组件的测试覆盖率可以达到 90% 以上了。
下一篇文章,我们通过具体的例子来实操一下。