单元测试 & mocha 简述

单元测试 & 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 举个例子

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

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的

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

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;
}

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

3 小结

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

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

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏抠抠空间

python中的Redis键空间通知(过期回调)

Redis是一个内存数据结构存储库,用于缓存,高速数据摄取,处理消息队列,分布式锁定等等。

2805
来自专栏IT开发技术与工作效率

东软邮箱设置 NeuSoft OutLook

1154
来自专栏栗霖积跬步之旅

异常:org.springframework.http.converter.HttpMessageNotReadableException

spring(springboot、springmvc)出现标题的异常一般是由于controller的入参失败引起的。

744
来自专栏web开发

初识NodeJS

1.JavaScript 模块化规范 浏览器环境 AMD Asynchronous Module Definition RequireJS CMD Com...

23410
来自专栏程序之美

socket异常问题

可能这两种代码看上去区别不大唯一区别就是输入输出流的关闭顺序。而这种顺序不同也会导致出错。

1514
来自专栏小勇DW3

Spring Boot应用总结更新

SpringBoot的产生背景伴随着微服务,微服务的相关概念参考上一篇的博客,分布式架构理论;

902
来自专栏专注 Java 基础分享

弄懂 JRE、JDK、JVM 之间的区别与联系

其实很多 Java 程序员在写了很多代码后,你问他 jre 和 jdk 之间有什么关系,jvm 又是什么东西,很多人不知所云。本篇不会讲述 jvm 底层是如何与...

3434
来自专栏决胜机器学习

Java初涉感悟

Java初涉感悟 (原创内容,转载请注明来源,谢谢) 一、概述 近期要接触到一些PHP转Java项目,用到的java框架是SpringBoot,故学习一些ja...

3234
来自专栏Python

python文件和目录操作方法大全

一、python中对文件、文件夹操作时经常用到的os模块和shutil模块常用方法。 1.得到当前工作目录,即当前Python脚本工作的目录路径: os.get...

1806
来自专栏黑白安全

Nipe – 脚本使Tor网络成为您的默认网关

此脚本可让您直接将所有流量从计算机传送到Tor网络,通过该网络您可以匿名浏览Internet,而无需担心被跟踪或追溯。

692

扫码关注云+社区