前端单元测试的好处是显而易见的,比如别人的代码我怎么改,新功能添加上了怎么保证旧功能没问题。而且现在都有测试驱动开发的概念了。但是呢,前端的单元测试究竟该怎么做?
假如我们是团队合作,我写的代码可能被其他人修改,即使是自己的代码也有可能在改动的时候出问题,我们需要测试,而且还需要将这些测试固化为代码。测试需要覆盖所有的逻辑,使得我们的代码质量得到保障,这也是单元测试的意义,并且测试用例需要小而精,覆盖率高,稳定。
怎么开始
测试需要测试框架+断言库,常用的测试框架是karma,moca。常用的断言库为assert,jasmine,expect,chai等
使用karma+jasmine+coverage
Karma是Testacular的新名字,在2012年google开源了Testacular,2013年Testacular改名为Karma。
Karma是一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其他代码编辑器一起使用。这个测试工具的一个强大特性就是,它可以监控(Watch)文件的变化,然后自行执行,通过console.log显示测试结果。
使用初始化命令,设置配置文件
开始测试
可以在chrome的控制台查看信息:
coverage
一般的测试我们需要查看测试覆盖率,在Karma中,可以通过karma-coverage查看覆盖率,修改配置文件如下:
可以查看测试覆盖率,一共有4个维度的测量数据:
注意测试要对每一个逻辑分支进行测试,才能保证测试覆盖率。
Jasmine
Jasmine是一个Javascript的BDD(Behavior-Driven Development)测试框架,不依赖任何其他框架。
基本语法介绍
describe(string, function)(测试套件,test suite)
可以理解为是一个测试集或者测试包(为了便于称呼,我们本文中统一叫测试集,官方称之为suite),主要功能是用来划分单元测试的,describe是可以嵌套使用的。
- 参数string:描述测试包的信息
- 参数function:测试集的具体实现
it(string, function)(测试用例,test case)
测试用例(官方称之为spec)
- 参数string:描述测试用例的信息
- 参数function:测试用例的具体实现
expect:断言表达式
每个测试文件中可以包含多个describe,每个describe中可以包含多个it,每个it中可以包含多个expect。
expect的使用
所有的expect都可以使用not表示否定的断言。下面是匹配器
- toBe:基本类型判断
- toEqual: toEqual有两种用法,对于基本的类型,toEqual相当于toBe,还可以用来判断对象。
- toMatch: 使用正则表达式判断
- toBeDefine: 判断是否是undefined
- toBeUndefined: 判断是否是undefined,与toBeDefine相反
- toBeNull:判断是否是null
- toBeTruthy:判断是否能转换成bool型,判断的是否是True
- toBeFalsy:判断是否能转换成bool型,判断的是否是False
- toContain: 判断集合是否包含(可以是普通类型,和可以是对象)
- toBeLessThan: 判断值类型的大小,结果若小则为True(也可以判断字符及字符串,以ascii码的大小为判断依据)
- toBeGreaterThan: 判断值类型的大小,结果若大则为True,与toBeLessThan相反(也可以判断字符及字符串,以ascii码的大小为判断依据)
- toBeCloseTo:判断数字是否相似(第二个参数为小数精度,默认为2位)
- toThrow: 判断是否抛出异常
- toThrowError: 判断是否抛出了指定的错误,判断是否是指定的错误
Setup和Teardown(钩子函数)
Jasmine允许在执行测试集/测试用例的开始前/结束后做一些初始化/销毁的操作,以下是提供的钩子函数:
Setup方法:
- beforeAll:每个suite(即describe)中所有spec(即it)运行之前运行
- beforeEach:每个spec(即it)运行之前运行
Teardown方法:
- afterAll:每个suite(即describe)中所有spec(即it)运行之后运行
- afterEach:每个spec(即it)运行之后运行
在beforeEach/it/afterEach中,还可以使用this关键字定义变量,需要注意的是,使用this关键字声明的变量,仅在beforeEach/it/afterEach这个过程中传递。
xdescribe/xit的使用
在实际项目中,需要由于发布的版本需要选择测试用例包,xdescribe和xit能很方便的将不包含在版本中的测试用例排除在外。不过xdescribe和xit略有不同:两者一个根本不会运行,另一个it会运行但是被挂起
- xdescribe:该describe下的所有it将被忽略,Jasmine将直接忽略这些it,因此不会被运行
- xit:运行到该it时,挂起它不执行
自动化单元测试
Karma+Jasmine+istanbul+webpack自动化单元测试,需要一个karma-webpack库,这是让karma可以去调用webpack,相当于一个桥梁。
具体配置可以参考如下:
istanbul的介绍
istanbul是一个单元测试代码覆盖率检查工具,可以很直观地告诉我们,单元测试对代码的控制程度。
覆盖率收集工具 nyc,是覆盖率收集工具 istanbul 的命令行版本,istanbul 支持生成各种格式的覆盖率报告。在 package.json 增加 nyc 的配置,告诉 nyc 该忽略哪些文件。
DOM交互单元测试
参考资料
Karma+Jasmine+istanbul+webpack自动化单元测试
《浏览器端测试:mocha,chai,phantomjs》
《测试用例:supertest》
javascript CI篇
测试框架 Mocha 实例教程
karma 测试框架的前世今生
Mocha+Chai+Istanbul单元测试
TypeScript 教程 单元测试