前言
作为前端程序员来说,大多数情况下我们测试代码的方式都是通过观察浏览器上的页面呈现和交互是否符合预期,基本不会去写什么自动化测试代码。毕竟想要写测试用例来覆盖大部分的使用场景也不是那么容易的事,单元测试还好点,端对端测试就没那么容易。我想大多数前端都跟我一样,没在项目里写过一些专门的测试用例吧?不是的话就很尴尬了,你也不会看到这篇文章了(手动滑稽)。
因此我对自动化测试这方面也没有多深入的了解,这次写这篇文章就是希望自己能够开始去了解如何对项目进行自动化测试,从而来保证自己的项目和代码质量。
如果是写一些基础组件或者工具插件什么的话,由于其内部代码不常变更,并且是复用较多的,就非常需要通过测试来保证内部代码的健壮性。此时自动化测试就显得非常重要了。因为自动化测试可以节省我们的测试时间,还能帮我们快速发现并且定位问题,从而提高我们的开发效率和代码质量。
但是不是所有代码都能测试,要想测试,就要把代码写得够规范,把代码尽量分离成单元可测的模块。比如一些不依赖于其他模块的通用的功能型函数。
测试工具
-
测试框架
测试框架可以让我们使用简洁的语法来写测试用例,以及对测试用例分组,在代码报错的时候也会捕获到并抛出Error,并附加一些说明信息。单元测试的框架主要有:
Mocha
,Jasmine
等,这里我使用的是Mocha
。mocha
是一款功能丰富的javascript单元测试框架,它既可以运行在nodejs环境中,也可以运行在浏览器环境中。 -
断言库
所谓断言,就是用来判断代码的输出是否与我们所期望的输出一致的。分为两种类型:
BDD
(行为驱动开发,主要是从用户的需求出发,强调系统行为)和TDD
(测试驱动开发,原理是在开发功能代码之前,先按照需要达到的目的来编写单元测试用例代码,以测试代码来确定编写和修补代码,以便通过测试)。TDD
的代表是assert
(也是nodeJS自带的断言库)。BDD
的代表有should.js
,expect.js
。chai.js
则是BDD/TDD 双模,同时支持 should / expect / assert 三种风格的断言库。
我这里先使用nodeJS自带的Assert
,毕竟刚入门,就先踩一下自带东西的坑,这也是我一直以来的习惯。
开始
安装mocha
新建一个目录test
,然后在该目录下执行npm install mocha
,将mocha框架安装到项目里,也可以使用-g
参数安装在全局。
然后在该目录下新建一个test.js
文件,内容如下:
//测试分组
describe('加法函数测试', () => {
//测试用例
it('1 加 1 应等于2', () => {
assert.equal(1 + 1, 2);
})
})
describe('真值测试', () => {
it('null', () => {
assert.ok(null, 'null不是真值')
})
it('true', () => {
assert.ok(true);
})
})
这里equal
内部使用的是相等运算符(==),使用全等运算符(===)的是strictEqual
方法。
assert断言库的其他API请查看 assert官方文档
果然原生的东西并没有好用到哪里去,都是使用assert对象暴露的方法,然后就只是简单的函数传参,测试代码看起来很不直观。
运行mocha
打开命令行工具,进入test
目录,如果你是将mocha安装在当前目录下,就执行./node_modules/.bin/mocha
。
为了方便执行测试命令,可以在package.json里配置一条测试用的’script’,例如:
{
"script":{
"test": "mocha test"
}
}
之后想跑测试代码的时候直接执行npm run test
命令就可以了。这是会自动执行test
目录(当前目录,不包含子目录)下的js测试文件。
如果想要执行子目录的js测试文件,就加上加上–recursive参数,这时test子目录下面所有的测试文件。
should.js
should.js
是TDD风格的断言库,与Node自带的assert相比,它的表达性更强更有用,非常语义化。先来看个例子:
describe('should.js断言库', () => {
it('1 加 1 应等于2', () => {
add(1,1).should.be.equal(2).and.be.a.Number();
})
})
可以看到should.js
的语法就像是在写自然语言一样,翻译成中文就是:”1+1的结果应该等于2并且是一个数字“。
其实我们也有办法将这些写法中文化,官方提供了extend、addChain、alias这几个方法,例如:
should.extend('应该', Object.prototype); // should 别名
['是', '个', '并且'].forEach((name) => { // 属性别名
should.Assertion.addChain(name);
});
// 方法别名
should.Assertion.alias('equal', '等于');
should.Assertion.alias('Number', '数字');
然后就可以将上面的测试用例改写成这样:
describe('should.js断言库', () => {
it('1 加 1 应等于2', () => {
add(1,1).应该.等于(2).并且.是.个.数字();
})
})
其他的判断方法跟Assert
的也差不多,就自行去官网学习咯。should.js官方文档(PS: should.js的官方文档是真的烂。
should.js比Node的assert模块有哪些好的地方
-
should.js通过扩展的方式来添加其判断的函数,保证了良好的扩展性。
-
语义化和链式调用。(should.js通过将一些语义词添加为属性值并返回Assertion对象本身,既具备语义化又可以实现链式调用)。
-
写法定制化。(就像刚刚那样,可以将写法改成中文的)
expect.js
这个好像没什么好讲的,跟should.js差不多,基于should.js简化的一个断言库。不过giuhub上好像有两个expect.js的仓库,两个的star数量都差不多,不知道哪个才是本尊。
chai.js
上面说了chai
支持TDD和BDD两种风格,TDD风格的assert
就不讲了,跟Node自带的Assert
也差不多。主要讲BDD的expect
和should
。
两者都是使用相同的链式语言来组织断言,但不同在于他们初始化断言的方式:
expect
使用构造函数来创建断言对象实例。
should
通过为Object.prototype新增方法来实现断言(所以should不支持IE);expect直接指向chai.expect,而should则是chai.should()
mocha + chai
Mocha实际上支持很多参数来提供很多灵活的控制,比如使用./node_modules/.bin/_mocha --require should
,Mocha在启动测试时就会自己去加载Should.js,这样就不需要手动require('should')
了。
更多参数配置可以查阅Mocha官方文档, 也可以在命令行使用’mocha –help’查看。这里介绍几个我认为比较有用的参数:
-
--reporter
:用来指定测试报告的格式,默认是
spec
格式。可以通过mocha --reporters
来查看所有可用的格式。 我比较喜欢list
,min
这两种格式 -
--bail
:--bail
参数指定只要有一个测试用例没有通过,就停止执行后面的测试用例。 -
--grep
--grep
参数用于搜索并执行匹配的测试用例(匹配it块的第一个参数)。 -
--compilers
如果测试脚本是用ES6写的,那么运行测试之前,需要先用Babel转码。这是就要用到`–compilers参数了。
-
--timeout
Mocha默认每个测试用例最多执行2000毫秒,否则报错。如果有异步操作的话,就需要用
-t
或--timeout
参数指定超时门槛。
在浏览器上运行mocha
除了在命令行运行,Mocha还可以在浏览器运行。执行mocha init
命令,生成初始化文件:
mocha init demo