前言

我的英文水平有点渣,所以就贴上原文给你们自己翻译了,还有github地址,如果发现有些中文文档的话也会顺便赠送飞机票

mocha

Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.

Mocha是一个能在nodejs和浏览器环境运行的有着丰富功能的javascript测试框架,使异步测试变得简单有趣,Mocha测试持续运行,能获得灵活和精确的报告,当发生未知错误能映射到正确的测试案例.
Mocha地址
Mocha中文文档
是一个很出名的测试框架了,估计有接触过测试代码的人都知道的东西

安装

npm install --global mocha

运行终端

mocha

系统会自动搜索当前目录下的test.js文件运行

should

should is an expressive, readable, framework-agnostic assertion library. The main goals of this library are to be expressive and to be helpful. It keeps your test code clean, and your error messages helpful.

By default (when you require('should')) should extends the Object.prototype with a single non-enumerable getter that allows you to express how that object should behave. It also returns itself when required with require.

It is also possible to use should.js without getter (it will not even try to extend Object.prototype), just require('should/as-function'). Or if you already use version that auto add getter, you can call .noConflict function.

Results of (something).should getter and should(something) in most situations are the same

should是一个可表达性,可阅读性,与框架无关的断言库,这个库的主要目标是变得可表达和可帮助,它使你的测试代码整洁和有帮助的错误信息.
默认(当你引入should)会在对象原型上扩展一个单独不可枚举的getter允许你去表达该对象应该的行为方式,当需要的时候它总是返回本身
它也可以在没有getter扩展的情况下使用(甚至不会尝试去扩展对象原型),只要引入(‘should/as-function’),或者如果你已经使用自动添加getter的版本,你能调用无冲突函数.
Results of (something).should getter 和 should(something) 在大多数情况下都是一样的
should.js地址
安装

npm install should --save-dev

断言库多种多样,这是比较出名的一款,但是个人感觉不好用,复杂的API,冗长的代码,推荐下面那一款

power-assert

Power Assert in JavaScript. Provides descriptive assertion messages through standard assert interface. No API is the best API.

power-assert在JS中通过标準的接口提供了描述性断言信息,没有API就是最好的API
power-assert地址
可以通过一行代码直观感受一下两个断言库的代码

should.js: (1).should.eql(10);
assert.js:  assert(1 === 10);

istanbul

Yet another JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests and browser tests. Built for scale.

另一个js代码覆盖工具,当运行的时候会通过模块加载钩子去计算语句,行,函和分支覆盖以明显地添加覆盖率,支持所有js覆盖使用案例包括单元测试,服务端函数式测试和浏览器测试,构建测试用例
istanbul地址

基本讲解

describe块就是测试套件,表示一组相关的测试,describe块里面可以包含多个describe块或者it块。
it块就是测试用例,表示一个单独的测试,it块可以包含多个断言块
assert块就是断言,判断预期结果和执行结果是否一致,失败的话会打印错误提示
注意:因为箭头函数不能够访问mocha的上下文,所以在需要用到mocha上下文的时候不能使用,否则报错。

同步测试

const assert = require('assert');

describe('你成年了么?', () => {
  it('我已经不是3嵗小孩了!', () => {
    assert(3 > 18);
  });
});

打开终端运行命令

mocha

会得出如下结果
![图片描述](attimg://article/content/picture/201810/06/163159awun6wq48y459kq6.png)
如果将代码换成assert(30 > 18)则如下
![图片描述](attimg://article/content/picture/201810/06/164259pdpp2epe5eeddfea.png)

异步测试

const assert = require('assert');

function timer(ms) {
  return new Promise(resolve => setTimeout(() => resolve(3), ms));
}

describe('你成年了么?', () => {
  it('我已经不是3嵗小孩了!', async () => {
    const age = await timer(1000);
    assert(age > 18);
  });
});

![图片描述](attimg://article/content/picture/201810/06/163908uyafs7d30yfqrldx.png)

钩子函数

mocha本身提供了多个钩子函数以供使用,官方摘抄如下:

run 'mocha spec.js'
|
spawn child process
|
|--------------> inside child process
  process and apply options
  |
  run spec file/s
  |
  |--------------> per spec file
    suite callbacks (e.g., 'describe')
    |
    'before' root-level pre-hook
    |
    'before' pre-hook
    |
    |--------------> per test
      'beforeEach' root-level pre-hook
      |
      'beforeEach' pre-hook
      |
      test callbacks (e.g., 'it')
      |
      'afterEach' post-hook
      |
      'afterEach' root-level post-hook
    |<-------------- per test end
    |
    'after' post-hook
    |
    'after' root-level post-hooks
  |<-------------- per spec file end
|<-------------- inside child process end
const assert = require('assert');

let a = 1;

describe('你成年了么?', () => {
  before('beforeEach', () => console.log(`before: ${a}`));
  beforeEach('beforeEach', () => console.log(`beforeEach: ${a}`));
  afterEach('afterEach', () => console.log(`afterEach: ${a}`));
  after('afterEach', () => console.log(`after: ${a}`));

  it('我已经不是3嵗小孩了!', () => {
    a = 2;
    assert(30 > 18);
  });
});

![图片描述](attimg://article/content/picture/201810/06/170918aadm9epv6gvwc8d2.png)

流程控制only(),ship()

就如字面意思一样,可以用来控制测试用例只执行或者跳过某些用例而不是采用注释的方法来改变测试用例

const assert = require('assert');

describe('你成年了么?', () => {
  it.skip('我已经不是3嵗小孩了!', () => {
    assert(30 > 18);
  });
  it.only('我是3嵗小孩!', () => {
    assert(3 > 18);
  });
});

![图片描述](attimg://article/content/picture/201810/06/171515zx9l9i1c1s19s9ww.png)
注意:流程控制不仅可以用在it块,也能用在describe块,例如:

const assert = require('assert');

describe('你成年了么?', () => {
  describe.skip('成年人', () => {
    it('我已经不是3嵗小孩了!', () => {
      assert(30 > 18);
    });
  });
  describe.only('未成年人', () => {
    it('我是3嵗小孩!', () => {
      assert(3 > 18);
    });
  });
});

![图片描述](attimg://article/content/picture/201810/07/111854spgb58immgpxxbxm.png)

多次测试retries()

有些时候不是一次测试就能达到要求的,mocha提供了retries()来设置重试次数,只要在超过次数并且都失败的情况下才会报错

const assert = require('assert');

describe('猜大小胜利的几率?', function() {
  it.only('我买大!', function() {
    this.retries(5);
    assert(Math.random() > 0.5);
  });
});

![图片描述](attimg://article/content/picture/201810/06/172022d6f1zcqcistj2cm9.png)

时间控制timeout()

如下所示:

const assert = require('assert');

function timer(ms) {
  return new Promise(resolve => setTimeout(() => resolve(3), ms));
}

describe('你成年了么?', function() {
  it('我已经不是3嵗小孩了!', async function() {
    this.timeout(500);
    const age = await timer(1000);
    assert(age > 18);
  });
});

![图片描述](attimg://article/content/picture/201810/07/114707v9020shs015u2yec.png)
注意:0是禁止超时,也可以用在钩子函数和describe块上

power-assert其他语法

assert(value, [message])
assert.ok(value, [message])
assert.equal(actual, expected, [message])
assert.notEqual(actual, expected, [message])
assert.strictEqual(actual, expected, [message])
assert.notStrictEqual(actual, expected, [message])
assert.deepEqual(actual, expected, [message])
assert.notDeepEqual(actual, expected, [message])
assert.deepStrictEqual(actual, expected, [message])
assert.notDeepStrictEqual(actual, expected, [message])

看起来种类繁多,其实都可以一个assert()实现,所以说No API is the best API。随便举个例子:

const assert = require('assert');

describe('全等比较?', function() {
  it('a和b全等么?', async function() {
    assert.deepStrictEqual(18, '18', 'a和b不全等!');
  });
});

![图片描述](attimg://article/content/picture/201810/07/145429b1sua1r27su7acc1.png)

istanbul

我们用istanbul来做结尾吧,这是一个测试代码覆盖率的库,跟上面两个没什么关系。主要是以下四个维度来测试执行代码率

Statements : 语句覆盖率
Branches : 分支覆盖率
Functions : 函数覆盖率
Lines : 行覆盖率

我们随便写一些加减乘除的测试代码

const a = 3,
  b = 18;

function add(a, b) {
  console.log(a + b);
}

function reduce() {
  console.log(a - b);
}

add(a, b);

然后运行

istanbul cover 你的js脚本名

![图片描述](attimg://article/content/picture/201810/07/151727srxavvairzrpyxvr.png)
然后当下目录还会生成一个coverage文件夹
![图片描述](attimg://article/content/picture/201810/07/152017jpracmzc8qay85pr.png)
具体作用我也没研究,但是里面的lcov-report是可以在浏览器打开的测试报告
图片描述

结语

mocha作为常规测试库,power-assert是简约的断言库,搭配istanbul做代码覆盖率可以满足一个基本需求了,因为我本身不会用到这些东西只是简单了解基础用法,上面例子都是在编辑器终端运行,实际开发中会嵌入项目package.json做特殊处理,有兴趣的可自行研究。


Afterward
621 声望62 粉丝

努力去做,对的坚持,静待结果