JS单元测试(UT)— Mocha

@一棵菜菜  August 12, 2019

前言

平时经常看到TDD(测试驱动开发)相关的文章或者内容,在上家公司时也常听到后端小伙伴说他正在写单元测试。。。所以心里就埋下了对单元测试的好奇,但由于种种原因没有及时去了解。最近发现单元测试还是有必要学习并使用的,所以就花了些时间学习,并整理成此文,方便后续回顾和查阅。

我的思维导图

UT.jpg

单元测试的意义

快速反馈你的功能输出,验证你的想法。
保证代码重构的安全性,没有一成不变的代码,测试用例能给你多变的代码结构一个定心丸。
易于测试的代码,说明是一个好的设计。

要依赖分离,一个类尽量保证功能单一,比如视图与功能分离,这样的话,你的代码也便于维护和理解。

为什么需要单元测试?

首先是一个前端单元测试的根本性原由:

  • JavaScript 是动态语言,缺少类型检查,编译期间无法定位到错误;
  • JavaScript 宿主的兼容性问题。比如 DOM 操作在不同浏览器上的表现。
  1. 正确性:测试可以验证代码的正确性,在上线前做到心里有底。
  2. 自动化:当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到保证。通过编写测试用例,可以做到一次编写,多次运行
  3. 解释性:测试用例用于测试接口、模块的重要性,那么在测试用例中就会涉及如何使用这些API。其他开发人员如果要使用这些API,那阅读测试用例是一种很好地途径,有时比文档说明更清晰。
  4. 驱动开发,指导设计(TDD):代码被测试的前提是代码本身的可测试性,那么要保证代码的可测试性,就需要在开发中注意API的设计,TDD将测试前移就是起到这么一个作用。
  5. 保证重构:互联网行业产品迭代速度很快,迭代后必然存在代码重构的过程,那怎么才能保证重构后代码的质量呢?有测试用例做后盾,就可以大胆的进行重构。

Mocha — JS测试框架

Mocha(['mɒkə],发音"摩卡")诞生于2011年,是现在最流行的JavaScript测试框架之一,在浏览器和Node环境都可以使用。

所谓"测试框架",就是运行测试的工具。通过它,可以为JavaScript应用添加测试,从而保证代码的质量。进行JavaScript单元测试(unit test)。

除了Mocha以外,类似的测试框架还有Jest、Jasmine、Karma、Tape等,也很值得学习。

安装

 npm install --save-dev mocha

测试脚本的写法

Mocha的作用是运行测试脚本,首先必须学会写测试脚本。

所谓"测试脚本",就是用来测试源码的脚本。

通常,测试脚本与所要测试的源码脚本同名,但是后缀名为.test.js(表示测试)。

比如,add.js的测试脚本名字就是add.test.js。

概念

测试脚本里面应该包括一个或多个describe块,每个describe块应该包括一个或多个it块。

1. describe块

describe块:"测试套件"(test suite),表示一组相关的测试。

它是一个函数(测试套件名称,实际执行的函数)

2. it块

it块:"测试用例"(test case),表示一个单独的测试,是测试的最小单位。

它也是一个函数(测试用例的名称,实际执行的函数)

3. 断言

断言:即判断源码的实际执行结果与预期结果是否一致,如果不一致就抛出一个错误。

断言功能由断言库来实现,Mocha本身不带断言库,所以必须先引入断言库。
断言库有很多种,Mocha并不限制使用哪一种。下面代码引入的断言库是chai,并且指定使用它的expect断言风格。
// 下载断言库chai
npm i chai --save-dev
// 测试脚本里引入断言库chai,并且指定使用它的expect断言风格
const { expect } = require("chai");

命令

1.npx mocha:Mocha默认只运行test文件目录下面第一层测试脚本。所以,一般都会把测试脚本放在test目录里面,然后执行npx mocha就不需要参数了。

2.npx mocha --recursive:test子目录下面所有的测试用例----不管在哪一层----都会执行。

3.npx mocha test/dir/*.js 指定执行test目录 > dir目录下的所有脚本

4.npx mocha --watch 监视指定的测试脚本,只要测试脚本有变化,就会自动运行Mocha

5.使用mochawesome模块,可以生成漂亮的HTML格式的报告(再在浏览器中打开html即可看到效果):

// 下载
npm install --save-dev mochawesome

// 执行测试并生成报告
npx mocha --reporter mochawesome --recursive

6.用package.json设置一个测试脚本:

"scripts": {
  "test": "mocha",
  // "test": "mocha -t 10000" // 将测试的超时时限指定为10000ms(如果有异步测试时要设置)
}

执行:

$ npm test

异步测试

Mocha默认每个测试用例最多执行2000毫秒,如果到时没有得到结果,就报错。对于涉及异步操作的测试用例,这个时间往往是不够的,需要用-t或--timeout参数指定超时门槛。

npx mocha -t 10000 -s 1000 
-t:将测试的超时时限指定为10000ms(默认2000ms)
-s:高亮显示耗时超过1000ms的测试用例(默认75ms)

done()函数

注意:it块执行的时候,传入一个done参数,当测试结束的时候,必须显式调用这个函数,告诉Mocha测试结束了。否则,Mocha就无法知道,测试是否结束,会一直等到超时报错。你可以把这行删除试试看。


我的代码例子

// 此处我使用的commonJS
// 引入断言库
const { expect } = require("chai");
// 引入被测试的js文件
const util = require("./util");

// 测试套件
describe("util测试1", () => {
  // 测试用例
  it("加法测试", () => {
    // 断言:调用add(1, 1),结果应该等于2
    expect(util.add(1, 1)).to.be.equal(2);
  });

  it("测试异步", (done) => {
    let y = 0;
    setTimeout(() => {
      y = 1;
      expect(y).to.be.equal(1);
      done(); // 通知Mocha测试结束
    }, 1000);
  });

  it("测试promise", () => {
    let x = 0;
    // 一定要return Promise
    return new Promise((resolve) => {
      setTimeout(() => {
        x = 2;
        resolve(x);
      }, 2000);
    }).then((data) => {
      expect(data).to.be.equal(2);
    });
  });
});
更多原文内容查看阮一峰《测试框架 Mocha 实例教程》
mocha官方文档
《浅谈前端单元测试》

评论已关闭