blog
blog copied to clipboard
TDD单元测试
TDD(Test Driven Development)
TDD就是先写测试, 后写程序
不是每个人都想写测试的, 很大原因是懒
:confused:我就是开发的, 跑一下看看就知道对不对, 要什么测试, 而且测试就是我写的, 没啥用啊
测试的意义
- 有说服力: 如果测试说测出bug了, 至少我能告诉他, 在这个case下程序是正确的
- 容易接手: 同事要辞职, 我却不能肯定他的代码对不对, 如果有测试就没这么多忧虑了
- 卖相好: 自己写一个项目, 写的明明比别人好, api比人家简洁, 但为啥大家不选我的项目呢. 这时候就要去看看是不是自己的测试用例不如别人长
TDD和Unit Test的关系
什么是Unit Test?
- Unit表示最小的测试单位, 不可再分, 因此Unit Test绝不包含逻辑
- 两个Unit Test Case之间没有依赖, 没有联系
- 可重复测试
TDD说的是什么时候测试, Unit Test说的是测试的是什么, 他们毫无关联
TDD和BDD
BDD是TDD的扩展, 本质是相同的, 但是API不同, 不过光是should.equal
, 就让人感觉有点蛋疼. 更别说还有to, be, been, is, that...
这一堆东西了
TDD一般用assert, 而nodejs自带了这个lib, 因此我毅然选择先入门TDD(喂我怎么又暴露自己不懂测试啊:scream:)
TDD是让测试来驱动开发, 因此我们很容易归纳出适用TDD的场景
- api明确
- 员工不靠谱, 需要约束
TDD的主要API(mocha给的, tdd本身只是说测试早于开发)
-
suite
-
test
-
ok
或者assert
:question:为什么光有assert还不行?
assert的功能简洁明了, 甚至是koa也直接用assert不用复杂的tdd测试框架
但大型项目中还是用测试框架为好, 因为assert是直接throw Error的,也就是只要出错即中断, 试想一下, 如果是10个人同时在搞这个项目, 测试用例跑不通, 但只看到一个错误, 那该有多蛋疼啊, 看不到错误的9个人只能干等着, 不知道后面还有没有错误
mocha学习
test
test用法很简单
test('api-1', function() {
ok(false, 'should true')
})
聪明的你一定想到了, test就俩作用, 一个是告诉框架这测试的是啥东西, 另一个就是第二个参数必然是由try catch包裹起来的, 这样我们可以完整的跑完所有test
test('api-1', function() {
ok(false, 'should true')
doSomethingElse() // 显然, 如果上面出错了, 这里是执行不到的
ok(true, 'should ok') // 除非是故意要全部正确, 不然连续写ok或者assert是没有意义的
})
但有一个例外, 即便错了还能执行下去, 这就是mocha中处理async(异步)的函数done
首先我们要知道这样写程序会出错, 因为setTimeout中的函数是没有上下文的, 不属于test里, 因此错误不会被catch
test('api-2', function() {
setTimeout(function() {
ok(false)
})
})
但我们用上done就不同了
test('api-2', function(done) {
setTimeout(function() {
ok(false)
done()
}, 1000)
})
这样连异步的错误都捕获了:smile:, 当然这也归功于nodejs中的uncaughtException
, 可以用process.on
进行捕获
suite
suite 这个函数就简单了, 意如其名, 一套, 用来将test归类, 相当于是一个namespace
mocha中用suite的ui(接口)有TDD和QUnit两种
TDD是这样的, 优点是可以嵌套
suite('Array', function(){
setup(function(){
// ...
});
suite('#indexOf()', function(){
test('should return -1 when not present', function(){
assert.equal(-1, [1,2,3].indexOf(4));
});
});
});
QUnit的优点是少了嵌套, 适用于api层级很平的项目, 不像TDD那样可以嵌套
suite('Array');
test('#length', function(){
var arr = [1,2,3];
ok(arr.length == 3);
});
test('#indexOf()', function(){
var arr = [1,2,3];
ok(arr.indexOf(1) == 0);
ok(arr.indexOf(2) == 1);
ok(arr.indexOf(3) == 2);
});
suite('String');
test('#length', function(){
ok('foo'.length == 3);
});
我个人很喜欢QUnit
, 写了还能前后端一起用