经常听到自动化测试,单元测试这种概念,一直以来我都处于一种概念性的了解。其实目前我们大环境下,还是很多公司对自动化测试这块没有那么重视,很多都还处于人工测试的阶段。改一个公用函数,我们生怕影响到所有的业务代码,靠人力,我们无法说服自己测试全面了。那么,自动化测试可以做到哪种地步呢?
什么是单元测试
我们有很多测试方法,单元测试、集成测试、端到端测试、可视化测试、功能测试等等等等。不同的人对不同的测试方法有不同的理解。
业界有这样的一种说法,单元测试和端到端测试是测试的两极,其余的测试都在在这两个测试范围中间。
这里我们只聊聊单元测试。那么,什么叫单元测试呢?顾名思义,就是以代码单元为单位的测试。这个代码单元可以是一个函数,一个对象,或者一个类。
其实在自动化之前,我们也在人工做单元测试。比如,本人写了如下一个函数:
校验这个函数写的对不对,常用操作就会在工作台先跑一下示例,看返回对不对。分别测一下:
1、没有输入url或者url格式不正确
2、参数格式校验是否正确
3、输入的url本身有/无参数 返回是否正确
4、输入的url带hash 返回是否正确
… (你还可以有更多)
以上呢,就是我们平时所谓的测试用例。
在没有所谓的自动化测试之前呢,我们一般都是通过人工跑示例测试的。而且,下次换个人开发,更改了这个函数,他自己默默又把这个测试用例都来一遍。现在我们引入单元测试,一个呢让测试更自动化更方便;二呢在不断迭代的过程中,以前的测试用例即可以保证新更改的正确性,又可以方便后面的开发更明了地理解代码实现了什么功能。
那么接下来,我将用一个简单的例子讲讲,怎么做的这个单元测试。
测试方案
简单测试工具介绍
现在市场上有很多测试工具:
- 测试框架: Mocha、Jasmine、Jest等等。提供一些清晰明了的语法对测试用例进行分组,描述,测试用例通过, 测试失败了(为什么)等等。Mocha对断言库和工作没做任何限制,比较灵活,相对比较成熟;Jasmine提供了自带的断言;Jest是facebook出品的,React官方推荐的单元测试框架。
- 断言库: Should.js、Chai等等,以及node自带的assert。
- 代码覆盖率: istanbul
- 测试平台: Karma
目录结构
这是我对测试目录的初步规划
当然业界也会有别的目录规划,直接把单元测试和被测试代码写在一个目录下:
不管哪种目录规划,我们都是有一个测试入口文件,作为执行测试用例的Setup。
拿第一种举例,入口文件:
karma配置
我们可以全局安装下karma-cli来初始化测试环境:
初始化测试环境:
PhantomJS是什么呢?如果有兴趣可以看看这里
提供一个浏览器环境的命令行接口,你可以把它看作一个“虚拟浏览器”,除了不能浏览,其他与正常浏览器一样。它的内核是WebKit引擎,不提供图形界面,只能在命令行下使用,我们可以用它完成一些特殊的用途
搭建测试环境需要的包:
配置项
简单的karma.conf.js配置如下:
测试用例怎么写
基本测试用例
先来一个最简单的测试用例。
在src/添加一个index.js
在spec/添加一个简单的测试用例:
然后我们在package.json中配置下test命令:
运行下npm run test
, 发现有报错。
因为我们的开发源码和测试用例都用了es6的语法,所以需要用Webpack处理一下。
karma.conf.js中增加webpack的配置:
再运行一下,我们就能看到以下界面啦
测试覆盖率和报告
在知道了测试结果是否成功之后,我们得有个清晰的认知啊。比如,是否每种情况我们都覆盖到了?这时候,我们就要引入覆盖率工具了。
什么叫代码覆盖率呢?
代码覆盖率描述的是代码被测试的比例和程度。简单地说,光是编写用例来测试代码,而不检查究竟哪些代码被测试过,哪些还没有测试过。
代码覆盖率有四个指标:
- 行覆盖率(line coverage):每一行执行情况
- 函数覆盖率(function coverage):每个函数调用情况
- 分支覆盖率(branch coverage):条件代码块执行情况
- 语句覆盖率(statement coverage):语句执行情况
示例
引入覆盖率工具包
如果想用别的报告配置,可以下载对应的插件(mocha-reporter之类)
做相关配置,最终版karma.conf.js如下:
此时运行测试,就会在test目录下生成coverage文件下,里面有相关测试报告,命令行也会有测试覆盖率的简单输出。
有什么条件没有运行到呢,打开coverage下的html
标黄的window.location.href就是没有测试到的条件。
怎么进行的覆盖率统计
生成的lcov.info
|
|
SF代表文件
FN代表函数,2代表函数开始的行数
FNF:1 表示一共有1个函数
FNH:1 表示有一个函数被测试用例覆盖
FNDA:4 表示函数被执行了4次
html文件里面是个网页报告
原理
大概原理就是,对源代码进行语法分析,插入覆盖率统计的代码,将执行统计结果放到对应的全局变量中,再将语法树转成js代码运行。在测试用例跑完之后再重新读取这些全局变量。