-
Notifications
You must be signed in to change notification settings - Fork 0
unit testing quick start
本文希望在半个小时内指引你快速上手单元测试,并且提供了一些必要的扩展参考链接。
目录
- 什么时候我们需要单元测试?
- 一些基本概念
- 编写单元测试
- 运行单元测试
- 手工运行测试
- 自动运行测试
显然不是所有的项目都需要单元测试,有些业务变更频繁,就没必要写;有些项目上线时间非常赶,那么也可以发布以后再慢慢补全。但是如果你在编写基础类库的代码,或者是非常重要的核心业务代码,那么单元测试就是必须的。
单元测试也不是所有项目一开始就要写(这和TDD不矛盾),在进行复杂项目的开发时,初期的编码经常会有较大调整来明确开发思路,这时候你完全不需要写测试,只需要编写 demo,快速验证结果即可。
总的来说,单元测试是保障代码质量的一个非常重要的方法(争论早已结束),所以在条件允许的情况下,要尽可能去写。
-
单元测试
针对程序的最小单位来进行正确性检验的工作。这个最小单元通常指函数或方法,是程序的最小可测试部件。
-
功能测试
根据程序的输入、输出和系统功能,从用户的角度针对软件界面、功能及外观进行的测试。
-
回归测试
根据在一个开发螺旋周期或者一个新版本的调试、维护或开发中产生的变化对程序加以测试。
-
持续集成
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。
此外,常接触的概念还有:UI 测试、兼容性测试、性能测试、测试覆盖率等。
值得注意的是,这些概念并不同通过某个单一的维度进行划分的,所以会有重叠,例如一个方法包含 DOM 操作,就是一个包含 UI 测试 的单元测试,而这个单元测试文件可能要在多浏览器中运行以通过 兼容性测试 ,也可能会通过某个系统进行 持续集成。
编写单元测试是件非常容易上手的事情,以 arale.event 为例:
events/
dist/
src/
tests/
events-spec.js
runner.html
readme.md
测试代码就放在 tests/ 文件夹中
events-spec.js
define(function(require) {
var Events = require('../src/events')
var expect = require('expect')
describe('Events', function() {
it('on and trigger', function() {
var obj = new Events()
obj.counter = 0
obj.on('event', function() {
obj.counter += 1
})
obj.trigger('event')
expect(obj.counter).to.equal(1)
obj.trigger('event')
obj.trigger('event')
obj.trigger('event')
obj.trigger('event')
expect(obj.counter).to.equal(5)
})
...
})
})
解读以上代码片段,由这么几个部分组成:
-
CMD 模块
- 最外层的
define(function(require){ … }表明这是一个 CMD 模块。 -
var Events = require('../src/events')获得我们要测试的Events模块。 -
var expect = require('expect')获得我们要使用的测试断言工具expect模块。
- 最外层的
-
测试套件
describe('Events', function(){ it('on and trigger', fn) …}是一个 测试套件, 其中describe()把所有Events模块的测试用例集合到一起,而it('on and trigger', fn)就是其中一个测试用例。测试套件我们推荐使用 mocha,文档还介绍了异步测试、指定超时以及测试用例的前置和后置处理
before(), after(), beforeEach(), 和 afterEach()等。 -
断言
expect(obj.counter).to.equal(1)和expect(obj.counter).to.equal(5)是两句断言,即判定 'on and trigger' 测试用例是否通过的语句。断言我们推荐使用 expect,文档全面介绍了各种断言的使用。
看,非常简单是不是,现在你已经能搞定一般的单元测试了。除此之外,还有什么问题我们可能会遇到呢?
-
监视、桩和仿制(spy, stub end mock)
可能你的代码中有用到外部库提供的 Ajax 功能,但你肯定不想还要搭建一个能真正处理 Ajax 请求的服务才能进行测试,这个时候需要有库帮你模拟这个 Ajax 请求的返回结果。
又或者你希望监视某个函数是否被调用或被调用的次数。
此类功能我们推荐使用 sinon 。
-
事件模拟
作为前端,写的代码免不了会包含各种浏览器端的操作,包括键盘、鼠标和触摸手势。我们需要触发相应的事件以确定 DOM 元素的表现是否正常或者绑定的方法是否正常工作。
该项功能我们推荐使用 event-simulate 。
编写 runner
runner.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Runner</title>
<link type="text/css" rel="stylesheet" charset="utf-8" href="http://modules.spmjs.org/gallery/mocha/1.8.1/mocha.css" />
<script src="http://modules.spmjs.org/seajs/1.3.1/sea.js"></script>
<script src="http://modules.spmjs.org/gallery/mocha/1.8.1/mocha.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>
(function() {
mocha.setup('bdd');
seajs.config({
preload: ['seajs/plugin-text','seajs/plugin-json'],
alias:{
"jquery":"gallery/jquery/1.7.2/jquery",
"$":"gallery/jquery/1.7.2/jquery",
"expect":"gallery/expect/0.2.0/expect.js",
"sinon":"gallery/sinon/1.6.0/sinon.js",
"event-simulate":"arale/event-simulate/1.0.0/event-simulate"}}
)
seajs.use(["./events-spec.js"], function() {
mocha.run()
})
})();
</script>
</body>
</html>
在你需要测试的浏览器中打开运行
你将看到如下运行结果
安装质量保障工具 totoro 后,无需手工编写 runner,命令行进入到 events/ 目录运行:
totoro test
然后工具就会自动帮你生成 runner 页面,在多浏览器中运行测试并返回详细的测试结果。
