前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单元测试 & mocha 简述

单元测试 & mocha 简述

作者头像
IMWeb前端团队
发布2019-12-04 12:38:51
7530
发布2019-12-04 12:38:51
举报
文章被收录于专栏:IMWeb前端团队

本文作者:IMWeb 黎清龙 原文出处:IMWeb社区 未经同意,禁止转载

单元测试 & mocha 简述

1. 单元测试

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证

这个最小测试单元,可以是一个函数,可以是一个类,可以是一个对象,也可以是一个组件,一个插件

在软件开发周期中,单元测试一直占据着很重要的位置,因为单元测试属于白盒测试,也是测试流中最前的一步,所以它起到非常重要的作用

但是,单元测试在前端领域并不被重视,前端程序员也没有写单元测试的习惯

但是,随着前端技术的发展,随着node的发展,越来越多“非UI”的前端代码出现

单元测试是保证代码质量的重要环节之一,特别是这些代码是会提供给其他人使用的时候,比如node插件,grunt插件等等

单元测试的作用有许多,下面列举一些:

  1. 保证代码可用
  2. 另一种纬度的文档
  3. 方便迭代回归
  4. 驱动开发

2. mocha

mocha是一个优秀的js测试框架,在许多开源插件的测试模块都可以看到它的影子

它支持TDD/BDD等多种流行的接口,也接受多种Assertions,如should.js/expect/chai/better-assert等,通过这些即可构建各种风格的测试用例

2.1 BDD

BDD(Behavior Driven Development),行为驱动开发是一种敏捷软件开发的技术,是一种理论方法学,具体的读者可深入学习,这里不做深入

BDD的接口有:

  • describe():描述场景,在里面可以设定Context,可包括多个测试用例,也可以嵌套场景
  • it():位于场景内,描述测试用例
  • before():所有测试用例的统一前置动作
  • after():所有测试用例的统一后置动作
  • beforeEach():每个测试用例的前置动作
  • afterEach():每个测试用例的后置动作

如果知道测试驱动开发,也可以理解BDD

2.2 Assertions

断言,在程序里面是确保“某个判断”是对的,如果错了,那程序就会有问题

每种程序语言都有原生的assertion模块,node的是assert模块

assertion模块的核心原理就是利用异常,如果判断是对的,则相安无事,如果错了,就会抛出一个异常

原生的assertion模块在语意上可能不是很直白,因此,有许多开源的assertion库,比如should.js/expect/chai/better-assert等,让assertion变得更加语义化,甚至可以让非程序员也能看得懂,这对于测试驱动开发有很大的帮助

2.3 举个例子

说了那么多,下面举个例子: 现在我们写一个数组去重的函数,并对这个函数进行单元测试,如下:

代码语言:javascript
复制
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,结果如下:

我们这里只测试了两个用例:

  1. 当传入数组是null或者是空数组的时候,返回的是空数组
  2. 应该返回一个新数组,并且是去重

实际上,每个测试用例都应该是遵循SPR的,前面两个测试用例都应该分开一些的,但为了篇幅考虑就组合到一起了

但是,这些测试够吗?

如果我们更加严谨的话,我们要求传入参数必须是数组

如果我们的需求是去重之后的数组必须是stable的

我们需要加上这两个测试用例:

代码语言:javascript
复制
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函数:

代码语言:javascript
复制
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;
}

再次执行测试,我们会发现测试用例都通过了:

3 小结

从上面的例子我们可以看到,利用mocha框架来构建单元测试用例是很简单的,构建的测试用例也非常简洁

另外,通过例子我们可以看到,在编写测试用例的时候是可以和代码本身分离的,读者可以看下测试用例的代码(忽略掉unique函数的实现代码,实际上测试代码和被测试代码本来就是分开的),可以说,这部分代码已经非常语义化了

最后,通过上面例子的推演,我们可以发现,测试用例不仅与被测试代码分离,它应该和需求紧密结合,unique之后的数组是不是stable的,那完全是看需求的。

另外,当组件版本升级的时候,功能可能变多了,那这时候相应的测试用例也应该加上,一个优秀的测试框架是应该很好的支持轻易添加测试用例的,比如mocha那样

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-10-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单元测试 & mocha 简述
    • 1. 单元测试
      • 2. mocha
        • 2.1 BDD
        • 2.2 Assertions
        • 2.3 举个例子
      • 3 小结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档