UXCore 组件单测的一些事儿

UXCore 是 XUX 团队开源的 PC 端 React UI 套件,做为一个支持企业级应用的 React UI 开源套件,为了保持项目的持续集成,良好的单元测试必不可少。本文来分享一下在编写单元测试的过程当中遇到的一些问题和总结。javascript

在编写单测的时候首先可能会遇到一个开发顺序的问题,是先写测试代码仍是先写程序代码,那么先来介绍两种开发技术:BDDTDD。BDD 是行为驱动开发,更趋向于需求,从写单测的顺序上能够理解为先了解行为,而后去写单测来检测是否符合需求指望;TDD 是测试驱动开发,先编写符合需求指望的测试,而后根据测试来实现最简功能代码,不断进行迭代打磨代码,在写单测的顺序上那就是先写单测,根据单测来编写功能代码。这两种开发技术分别适用于不一样的场景,可根据本身的状况来选择使用。html

UXCore 目前已有的组件采用的是 BDD ,因为组价代码都已 ready 咱们就编写测试来验证需求是否已经知足,首先要作的就是通读组件代码(由于有的组件的做者不是本身),将其内部逻辑和实现要搞清楚,接下来才会知道怎么具体写测试代码!java

UXCore 组件单测环境

在编写单测时咱们要将测试代码运行起来,实时看到测试结果,而且要查看测试覆盖率以更好的提升代码质量,那么这就须要测试运行器、测试框架等等工具或框架来支持,如下是 UXCore 组件采用的单测环境,其余 React 项目也可参考使用。node

  1. 测试运行器(Test runner)主要负责测试的自动化,它能够自动调起多种浏览器或者 js 环境让你来调试测试代码。目前有 JSTDKarmaTestSwarmBuster 等测试运行器,UXCore 使用的是 Karma ,缘由是它集成了 Istanbul 的 coverage 功能,可检测测试覆盖率,而且支持多种测试框架。在 uxcore-tools 中已经集成 karma ,你只需执行几个命令就能够。react

  2. 测试框架(Testing Framework),即运行测试的工具,测试框架规定了测试风格和测试的生命周期,经过测试框架为程序添加测试,保证代码质量。目前有 JasmineQunitSinonMocha 等测试框架。UXCore 选择的是 Mocha ,它来自 TJ 大神,不但能够在bash中进行测试,并且还拥有一整套命令对测试进行操做,Mocha 的异步测试作的比较好,在 it 的回调函数中会获取一个参数 done ,类型是 function ,用于异步回调,当执行这个函数时就会继续测试。jquery

  3. 固然,除了测试运行器 、测试框架以外咱们还须要断言库(Assertion library)来帮助咱们判断代码执行的正误,比较流行的断言库有:expect.jsshouldchai,咱们使用的是 expect.js ,支持 IE6+ ,语法通俗易懂。git

  4. 在测试 react 组件时还要用到 React UI 测试库,React 官方提供了工具库,它对虚拟 DOM 和 真实 DOM 都有对应的测试方法,可是它使用起来不太方便。还有一个 Airbnb 公司的封装的 Enzyme ,很是容易上手。咱们选择的是后者。github

测试覆盖率

测试覆盖率是测试中的一种度量,描述源代码被测试的比例和程度。经过测试覆盖率能够检测哪些代码没有被测试,可是测试覆盖率并不能做为衡量代码质量的标准和目标,而是一种发现未被测试代码的手段。npm

覆盖率的统计的核心思想就是,在源代码对应的位置注入统计代码,当代码运行后,根据统计代码统计的数据肯定程序运行的路径,最终生成覆盖率统计报告。整个过程能够分为三部分:转换(instrument)、执行(run)、生成报告(report)。api

  1. 转换(instrument)

    • 首先对源代码进行语法分析生成语法树

    • 在语法树相应的位置注入统计代码,在程序执行到这个位置的时候对相应的全局变量赋值,确保执行以后可以根据全局变量知道代码的执行流程

    • 根据注入以后的语法树生成对应的 JavaScript 代码,即转换以后的代码(instrumented code)

注:这里进行语法分析的好处是,针对书写不规范的代码(好比一行多个语句),依然可以很好统计出分支覆盖和组合覆盖等信息。反过来想,若是想要提升覆盖率,那么代码要书写规范。

  1. 执行(run)

这一步须要先载入转换后的代码:

  • 浏览器环境:须要将转换后的代码传给浏览器。若是是 karma 之类的带 server 的测试框架,须要经过 socket 传输至浏览器,执行完以后再将包含覆盖率信息的执行结果传回 server ,生成测试报告。

而后执行单元测试,产生的统计信息会挂在全局变量 this 下面。对于浏览器环境,this 就是 window。

  1. 生成报告(report)

这一步会根据全局标量中的覆盖率信息生成特定格式的报告,如 html、lcov、cobertura、teamcity等。

想要了解更详细的内容可移步:https://yq.aliyun.com/article...,若是想了解 Istanbul入门使用的童鞋能够看一下阮大神的这篇。

如何编写 React 组件单测

编写单元测试就是用一段代码来测试一个模块或功能是否能达到预期结果的一个过程。

下边列出两个常见的例子给你们做为参考:

  1. 最简单的 props 测试。

    • 首先建立组件的真实 DOM 结构

    const wrapper = mount(<Select2 prefixCls="kuma-select2" ></Select2>);
    • 而后获取到当前组件的 prefixCls props,用 enzyme 的 .props() API 就能够很容易的取到 props 的值(这里有一点要说明,.props() 只能取到 root component 的 props),而后用断言句进行判断当前的 prefixCls 是不是 'kuma-select2'

    expect(wrapper.props().prefixCls).to.equal('kuma-select2');
    • 完成上边两步就能够了吗?上边只是 get props 符合了咱们的指望,那咱们再给组件更新一下 props 看会不会生效。enzyme 也提供了对应的 .setProps() 的 API ,真是太方便啦。而后再次验证新的 prefixCls 有没有更新。

    wrapper.setProps({ prefixCls: 'kuma-select2-test' });
    expect(wrapper.props().prefixCls).to.equal('kuma-select2-test');
  1. 模拟下拉框选中动做,测试 value 值是否已更新。

    • 首先仍是建立组件的真实 DOM 结构

    const wrapper = mount(<CascadeSelect options={options} />);
    • 而后要建立 Trigger 组件( dropdown的子组件 )的真实 DOM 结构,这里要提一下 enzyme 的 .find() API ,它的参数除了能够是选择器外还能够是子组件的名称。

    const dropdownWrapper = mount(wrapper.find('Trigger').node.getComponent());
    • 接下来找到下拉选项中的第一项触发 click 事件,.simulate() API 用来作事件绑定。

    dropdownWrapper.find('li').at(0).simulate('click');
    • 模拟完后就来验证你要验证的逻辑,获取到子组件 CascadeSubmenu 的一项 option ,调用 CascadeSubmenu 的 props onItemClick 函数,将获取到的 option 传入进去,最后断言句判断最后组件的 value 是否不为空。

    const option = dropdownWrapper.find('CascadeSubmenu').props().options[0];
    dropdownWrapper.find('CascadeSubmenu').props().onItemClick(option,2,false);
    expect(wrapper.state('value').length > 0).to.be.ok()

上边的代码使用了 Enzyme 的 Full DOM Rendering API ,首先建立 CascadeSelect 组件的真实 DOM 结构,而后再次建立 dropdown 的 Trigger 子组件的真实 DOM 结构,最后找到第一个选项触发 click 事件。

Tip:若是组件引用了其余的组件,那么单测应该测到什么程度呢?要不要测引用的其余组件的代码?答案就是:你不须要测试它引用的组件的代码逻辑,引用组件的代码测试会在它本身内部完成,固然你测了也不会提升覆盖率,咱们只需测试咱们组件的代码便可。

最后,怎么能更加清晰的知道本身哪些代码尚未覆盖到呢?若是能够看到就行了,可以对症下药,绝对提升覆盖率啊!固然,Karma 都帮你作好了,执行过 coverage 后会生成一个 coverage 目录,它的 src 目录下的组件文件命名的 html 文件打开后就会看到很是清晰的记录,红色的表示尚未覆盖到的。固然也能够本地起一个服务,可用 anywhere 直接浏览器里查看覆盖率列表和对应的详细文件。下图是一份coverage 报告。

相关文章
相关标签/搜索