本文作者:IMWeb 黎清龙 原文出处:IMWeb社区 未经同意,禁止转载
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证
这个最小测试单元,可以是一个函数,可以是一个类,可以是一个对象,也可以是一个组件,一个插件
在软件开发周期中,单元测试一直占据着很重要的位置,因为单元测试属于白盒测试,也是测试流中最前的一步,所以它起到非常重要的作用
但是,单元测试在前端领域并不被重视,前端程序员也没有写单元测试的习惯
但是,随着前端技术的发展,随着node的发展,越来越多“非UI”的前端代码出现
单元测试是保证代码质量的重要环节之一,特别是这些代码是会提供给其他人使用的时候,比如node插件,grunt插件等等
单元测试的作用有许多,下面列举一些:
mocha是一个优秀的js测试框架,在许多开源插件的测试模块都可以看到它的影子
它支持TDD/BDD等多种流行的接口,也接受多种Assertions,如should.js/expect/chai/better-assert等,通过这些即可构建各种风格的测试用例
BDD(Behavior Driven Development),行为驱动开发是一种敏捷软件开发的技术,是一种理论方法学,具体的读者可深入学习,这里不做深入
BDD的接口有:
如果知道测试驱动开发,也可以理解BDD
断言,在程序里面是确保“某个判断”是对的,如果错了,那程序就会有问题
每种程序语言都有原生的assertion模块,node的是assert模块
assertion模块的核心原理就是利用异常,如果判断是对的,则相安无事,如果错了,就会抛出一个异常
原生的assertion模块在语意上可能不是很直白,因此,有许多开源的assertion库,比如should.js/expect/chai/better-assert等,让assertion变得更加语义化,甚至可以让非程序员也能看得懂,这对于测试驱动开发有很大的帮助
说了那么多,下面举个例子: 现在我们写一个数组去重的函数,并对这个函数进行单元测试,如下:
var should = require('should');
function unique(arr) {
var ret = [];
var obj = {};
if (arr && arr.length) {
arr.forEach(function(v) {
obj[v] = 1;
});
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
ret.push(k);
}
}
}
return ret;
}
describe('unique', function() {
it('should return empty array when the argument is null or empty array', function() {
unique(null).should.be.eql([]);
unique([]).should.be.eql([]);
});
it('should return a new array of uniqued items', function() {
var testArr = [2, 1, 3, 1, 2, 2, 1, 4];
var cloneArr = testArr.slice();
var uniArr = unique(testArr);
uniArr.should.have.length(4);
uniArr.should.containDeep([1, 2, 3, 4]);
testArr.should.be.eql(cloneArr);
});
});
执行mocha test.js
,结果如下:
我们这里只测试了两个用例:
实际上,每个测试用例都应该是遵循SPR的,前面两个测试用例都应该分开一些的,但为了篇幅考虑就组合到一起了
但是,这些测试够吗?
如果我们更加严谨的话,我们要求传入参数必须是数组
如果我们的需求是去重之后的数组必须是stable的
我们需要加上这两个测试用例:
it('should return empty array when the argument is not an array', function() {
unique({
length: 1
}).should.be.eql([]);
});
it('should return a stable array', function() {
unique([2, 1, 3, 1, 2, 2, 1, 4]).should.be.eql([2, 1, 3, 4]);
});
运行测试会发现这两个用例失败了:
用例不过,于是,我们修改我们的unique函数:
function unique(arr) {
var ret = [];
var obj = {};
if (arr && arr instanceof Array) {
arr.forEach(function(v) {
if (!obj[v]) {
ret.push(v);
obj[v] = 1;
}
});
}
return ret;
}
再次执行测试,我们会发现测试用例都通过了:
从上面的例子我们可以看到,利用mocha框架来构建单元测试用例是很简单的,构建的测试用例也非常简洁
另外,通过例子我们可以看到,在编写测试用例的时候是可以和代码本身分离的,读者可以看下测试用例的代码(忽略掉unique函数的实现代码,实际上测试代码和被测试代码本来就是分开的),可以说,这部分代码已经非常语义化了
最后,通过上面例子的推演,我们可以发现,测试用例不仅与被测试代码分离,它应该和需求紧密结合,unique之后的数组是不是stable的,那完全是看需求的。
另外,当组件版本升级的时候,功能可能变多了,那这时候相应的测试用例也应该加上,一个优秀的测试框架是应该很好的支持轻易添加测试用例的,比如mocha那样
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有