本文主要介绍基于 React 框架的项目,在对自己封装组件或者是通过 HOC , render props 的方式在第三方 UI 组件库(e.g. Ant Design)的基础上封装的公共组件的自动化测试技术选型以及在项目中的实践
在多人协作的项目中,特别是项目团队中,会有多个技术选型类似的项目,例如是都是通过 React 全家桶搭建的项目。随着项目的业务逻辑逐渐增加,我们都会抽取其中一些公共的代码,特别是一些与业务没有强耦合的组件,组成一个基础公共组件库,提供给各个项目使用。听起来很美好,但是在实际工程实践方面,会产生一些问题:
如何保组件库的质量?如何确保修改更新不会影响其他的项目?如何最快地回归测试?
为了解决上面的问题,我们自然就会想到,其实我们需要一个自动化测试,我们在项目中的选型是这样的:
假设你们多个项目都在使用一个叫做 Component
的公共组件库,你现在需要通过通过测试的方式来保证这个库能在各个项目中稳定运行。你应该怎么样着手开始做这个事情? 做到 coverage
100%就可以了吗?当然这是我们一直追求的目标,但是,在绝大多是的情况下,我们并不需要完全覆盖所有的代码?
为什么呢? 其实我们都知道,即使我们真的覆盖了 100% 的代码,也没有办法保证该组件是没有bug的。所以不要为了追求代码覆盖率达到 100% 而写一些无意义的测试用例,但是要尽量覆盖了组件的主要逻辑。
<Input />
组件,在你写测试用例的时候你应该跳过这个组件,因为你不对这个组件负责,并且选用第三方库的时候,应该留意这个第三方库的测试用例是否全面的,因为这直接可以判断这个第三方库是否可靠的。下面来聊一下如何写测试用例,我总结分为两个方法:
建议阅读下面内容之前,先了解一下 Enzyme 的基本 api: https://github.com/airbnb/enzyme
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 来测试,而不用测试其中的逻辑。
但是这对于复杂的组件来说,是完全不够的,因此,我们还需要测试组件的逻辑。
一个需要被测试的组件往往只需要创建一个 snapchat,具体的使用方法可以像上面的说明一样操作,没必要创建多个 snapshot。
测试 props 主要分为两步走:
defaultProps
进行组件的渲染。setProps
的方式设置组件的 props,测试其 props 是否正常渲染我需要的东西。通过 snapshot 测试和 props 测试,已经能确保组件是可以正常渲染的了,但是这还远远不够,因为有很多分支代码我们是没有覆盖到的,如果你查看 jest --coverage
, 你会发现还有很多触发事件的函数没有被覆盖,所以这里我们需要模拟一些事件测试。
通常来说比较常用的3个测试事件的方案是:
如果要测试 state,那么需要写两个测试用例
当你按照前面 4 个步骤写下来,基本上组件的测试覆盖率可以达到 90% 以上了。
下一篇文章,我们通过具体的例子来实操一下。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。