组里马上要转变开发模式,由传统的开发模式(Developer开发,QA测试),转变为尝试TDD(Test-driven development,测试驱动开发)的开发模型。由此将不存在QA的角色,或者仅存很少的QA用于系统模块间的集成测试。
因此代码的测试与开发都将由开发者(Developer)来保证。
这就需要借助优秀测试框架的帮助,尤其是支持TDD开发模式的自动化测试框架更为重要,因为我使用的编程是语言是Node.js,那么广泛使用的Mocha.js将成为我的首选。
在团队转型过程中,很多事情都要大家自己摸索。对于Node.js的TDD开发模式,我也做了些入门的学习。
首先来了解下什么是TDD。
一. 什么是TDD?
通过*关于TDD的介绍,可知,TDD,全称Test-driven Development,中文测试驱动开发,是来源于Agile敏捷开发的一个极限编程思想。
大致是讲,Developer开发之前,先写测试用例(test case),测试用例写好后,再来实现需要实现的方法或功能,然后跑一遍测试用例,看能否通过。将来新加功能时,也是先加测试用例,然后新功能实现后,再跑一遍所有的测试用例,如果所有用例都成功(Pass),那么则代码质量可以保证。
下图是来自*的TDD模式流程图。
大概就是这样一个流程。
在TDD的设想中,测试用例为先,是第一要务。
除了TDD外,还有ATDD和BDD的概念。BDD的概念用的很多,简单介绍一下。
1. TDD 与 BDD
BDD是Behaviour-driven Development,行为驱动开发,相比TDD,BDD更关注通过测试,观察到程序的行为是否正确,因此它的接口是使用describe。而与BDD相比,TDD更偏重与测试代码的功能是否实现正确,它的接口是suite。因为我也是初学,其中差别理解不深。但对我而言,好用,适合才是更重要,因此我还是会选择TDD为切入点,以后可能会根据实际调整。
2. Test Suite
由上可知,TDD的接口使用的是suite。那这里必须要介绍下Test Suite的概念,在*中,
Test Suite:a collection of test cases that are intented to be used to test a software program to show that it has same specified set of behaviours.
其实suite就是一组测试用例的集合,可用于对测试用例进行分类。suite里面可以嵌套suite,就像测一个功能的一组测试例子里面再细分测不同小功能的机组测试例子。
3. Test Case测试用例的结构
我们在写测试用例时,一个被广泛接受的结构是:
a. Setup: 准备好环境和数据,跑这个测试用例之前的准备
b. Execution:执行测试(测试用例的实现的主要代码)
c. Validation:验证结果
d. Cleanup:现场恢复,一般与a相反。不影响跑后面的测试用例。
介绍完TDD的概念和接口,下面就可以引入Mocha.js啦。
二. Mocha.js - Javascript测试框架,支持TDD,BDD等多种接口
Mocha.js是被广泛使用的Javascript测试框架,官网:http://mochajs.org/
官方对其的定义是:
Mocha is a feature-rich JavaScript test framework running on node.js and the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases.
使用Mocha.js,可以写测试用例,并跑用例来得到结果,同时还支持多种格式的Report来显示结果。支持TDD,BDD等接口,是TDD开发过程中的好帮手。
由于TDD和BDD,Mocha提供的接口不同,这里我的例子主要是使用TDD。
首先要安装Mocha.js,可通过NPM
npm install -g mocha
安装好后,可使用mocha命令来使用mocha提供的功能。
例如mocha -h可查看命令帮助,如下。
在这里,我实现一个简单常见的测试用例,来说明Mocha.js如何使用。
首先介绍一下几个重要的接口,
suite:定义一组测试用例。
suiteSetup:此方法会在这个suite所有测试用例执行前执行一次,只一次,这是跟setup的区别。
setup:此方法会在每个测试用例执行前都执行一遍。
test:具体执行的测试用例实现代码。
teardown:此方法会在每个测试用例执行后都执行一遍,与setup相反。
suiteTeardown:此方法会在这个suite所有测试用例执行后执行一次,与suiteSetup相反。
这些接口都是与TDD概念中的接口对应与相关实现,方便组织测试用例。BDD的接口在这里不予赘述,可参考官方文档。
测试用例代码如下:
var assert = require('assert');
var mocha = require('mocha'); var suite = mocha.suite;
var setup = mocha.setup;
var suiteSetup = mocha.suiteSetup;
var test = mocha.test;
var teardown = mocha.teardown;
var suiteTeardown = mocha.suiteTeardown; //test case
suite('Array', function(){ suiteSetup(function(){
//suiteSetup will run only 1 time in suite Array, before all suite
//...
console.log('suitSetup...');
}); setup(function(){
//setup will run 1 time before every suite runs in suite Array
//...
console.log('setup...');
}); suite('indexOf()', function(){
test('should return -1 when not present', function(){
assert.equal(-1, [1, 2, 3].indexOf(4));
});
}); suite('indexOf2()', function(){
test('should return not -1 when present', function(){
assert.equal(0, [1, 2, 3].indexOf(1));
});
}); teardown(function(){
//teardown will run 1 time after every suite runs in suite Array
//...
console.log('teardown...');
}); suiteTeardown(function(){
//suiteTeardown will run 1 time in suite Array, after all suits run over.
//...
console.log('suiteTeardown...');
});
});
执行这个测试用例,通过如下命令:
mocha test.js
结果如下:
可以看到2个测试例子都Pass,另外通过打印的信息,可看到不同接口的使用区别。这些都方便以后写正确的测试用例。
总之,可见,有了Mocha.js的帮助,TDD的Node.js开发讲变得很容易。
三. 关于TDD的一些感想
以前看过陈皓的一篇文章,讲TDD其实没有看上去那么美。通过自己接触以来,发现了一些难做到的地方或小问题,如下:
1. 测试用例难写
要针对不同功能的Module,写出能准确测试其功能的用例,不是件容易事,可能会花费很多时间和精力。而Developers往往更倾向于把精力主要用在功能的实现。
2. 要维护大量的测试用例
功能复杂的Module,测试用例的数量也多,固然每次修改代码后,跑一遍所有的例子很cool,但是如果功能代码经常需要变动,测试用例也要经常变动,需要花费精力维护。
不管怎样,变化总是会带来好事,拥抱变化。在摸石头过河中,探索适合自己的开发模式才重要。希望真正的开发任务到来之后,能不断总结遇到的问题,并根据自己的实际需求,找到适用自己的模式和路子:-)
四. 参考文档
1. http://en.wikipedia.org/wiki/Test-driven_development
2. http://en.wikipedia.org/wiki/Test_suite
3. http://mochajs.org/
Kevin Song
2015年6月9日