博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习测试框架Mocha
阅读量:5082 次
发布时间:2019-06-13

本文共 21324 字,大约阅读时间需要 71 分钟。

学习测试框架Mocha

注意:是参考阮老师的文章来学的。虽然阮老师有讲解,但是觉得自己敲一遍,然后记录一遍效果会更好点。俗话说,好记性不如烂笔头。

   Mocha 是javascript测试框架之一,可以在浏览器和Node环境下使用,除了Mocha测试框架之外,类似的测试框架还有Jasmine, Karma, Tape等。

可以使用npm全局安装:如下命令:

npm install -g mocha

也可以作为项目的依赖进行安装,如下命令:

npm install --save-dev mocha

如下所有的测试代码在github上,

Mocha的作用是运行测试脚本,我们先来编写一个js代码吧,下面是一个简单的加法模块 add.js代码:

function add(x, y) {  return x + y;}module.exports = add;

要测试上面的代码是否对的,因此就要编写测试脚本,测试脚本与所要测试的源码脚本同名,但是后缀名为 .test.js或 .spec.js, 如:xx.test.js 或 xx.spec.js,比如上面的add.js的测试脚本可以叫 add.test.js 或 add.spec.js,因此我们可以在add.js的同目录下新建 add.test.js,(可以查看demo1文件代码)

编写代码如下:

var add = require('./add.js');var expect = require('chai').expect;describe('加法函数的测试', function() {  it('1加1应该等于2', function() {    expect(add(1, 1)).to.be.equal(2);  });});

如上代码就是一个测试脚本代码,测试脚本可以包含一个或多个describe块,describe块称为 "测试套件",表示一组相关的测试,它是一个函数,有两个参数,第一个参数是测试套件的名称,第二个参数是一个实际执行的函数。

每个describe块也可以包含一个或多个it块,it块称为 "测试用例",表示一个单独的测试,是测试的最小单位,它也是一个函数,第一个参数也是测试用例的名称,第二个参数是一个实际执行的函数。

二. 理解断言库

断言库可以理解为比较函数,也就是断言函数是否和预期一致,如果一致则表示测试通过,如果不一致表示测试失败。mocha本身是不包括断言库的,所以必须引入第三方断言库的,目前比较受欢迎的断言库有 should.js, expect.js, chai.
should.js BDD风格
expect.js expect风格的断言
chai expect(), assert() 和 should的断言
Mocha默认使用的是BDD的风格。expect和should都是BDD的风格,二者使用相同的链式语言来组织断言的,但不同在于他们初始化断言的方式,expect使用
构造函数来创建断言对象实例,而should通过为 Object.prototype新增方法来实现断言(should不支持IE),expect直接指向 chai.expect,
should则是 chai.should();

上面的代码中 expect 是断言的意思,该作用是判断源码的实际执行结果与预期结果是否一致,如果不一致就抛出一个错误,因此在执行上面代码之前,

我们需要在项目中安装 chai, 如下命令:

npm install --save-dev chai

所有的测试用例(it块)都应该含有一句或多句断言,是编写测试用例的关键,Mocha本身不包含断言,断言是由断言库来实现的,因此需要先引入断言库。

如下代码:

var expect = require('chai').expect;

上面代码是引用 chai 断言库,使用的是 expect断言风格。

expect

如下是一些常用的比较;

// equal 相等或不相等expect(4 + 5).to.be.equal(9);expect(4 + 5).to.be.not.equal(10);expect('hello').to.equal('hello');  expect(42).to.equal(42);  expect(1).to.not.equal(true);  expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });  expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });// above 断言目标的值大于某个value,如果前面有length的链式标记,则可以用来判断数组长度或者字符串长度expect(10).to.be.above(5);expect('foo').to.have.length.above(2);  expect([ 1, 2, 3 ]).to.have.length.above(2); 类似的还有least(value)表示大于等于;below(value)表示小于;most(value)表示小于等于// 判断目标是否为布尔值true(隐式转换)expect('everthing').to.be.ok;expect(1).to.be.ok;  expect(false).to.not.be.ok;expect(undefined).to.not.be.ok;  expect(null).to.not.be.ok; // true/false 断言目标是否为true或falseexpect(true).to.be.true;  expect(1).to.not.be.true;expect(false).to.be.false;  expect(0).to.not.be.false;// null/undefined 断言目标是否为null/undefinedexpect(null).to.be.null;  expect(undefined).not.to.be.null;expect(undefined).to.be.undefined;  expect(null).to.not.be.undefined;// NaN  断言目标值不是数值expect('foo').to.be.NaN;expect(4).not.to.be.NaN;// 判断类型大法(可以实现上面的一些例子):a/anexpect('test').to.be.a('string');expect({ foo: 'bar' }).to.be.an('object');expect(foo).to.be.an.instanceof(Foo);expect(null).to.be.a('null');  expect(undefined).to.be.an('undefined');expect(new Error).to.be.an('error');expect(new Promise).to.be.a('promise');// 包含关系:用来断言字符串包含和数组包含。如果用在链式调用中,可以用来测试对象是否包含某key 可以混着用。expect([1,2,3]).to.include(2);expect('foobar').to.contain('foo');expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');// 判断空值expect([]).to.be.empty;expect('').to.be.empty;expect({}).to.be.empty;// matchexpect('foobar').to.match(/^foo/);    // exist 断言目标既不是null也不是undefinedvar foo = 'hi' , bar = null, baz;expect(foo).to.exist;  expect(bar).to.not.exist;  expect(baz).to.not.exist;// within断言目标值在某个区间范围内,可以与length连用expect(7).to.be.within(5,10);  expect('foo').to.have.length.within(2,4);  expect([ 1, 2, 3 ]).to.have.length.within(2,4);// instanceOf 断言目标是某个构造器产生的事例var Tea = function (name) { this.name = name; } , Chai = new Tea('chai');expect(Chai).to.be.an.instanceof(Tea);  expect([ 1, 2, 3 ]).to.be.instanceof(Array); // property(name, [value])  断言目标有以name为key的属性,并且可以指定value断言属性值是严格相等的,此[value]参数为可选,如果使用deep链式调用,可以在name中指定对象或数组的引用表示方法// simple referencingvar obj = { foo: 'bar' };  expect(obj).to.have.property('foo');  expect(obj).to.have.property('foo', 'bar');// 类似于expect(obj).to.contains.keys('foo')// deep referencingvar deepObj = {    green: { tea: 'matcha' },  teas: [ 'chai', 'matcha', { tea: 'konacha' } ]};expect(deepObj).to.have.deep.property('green.tea', 'matcha');  expect(deepObj).to.have.deep.property('teas[1]', 'matcha');  expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); // ownproperty 断言目标拥有自己的属性,非原型链继承expect('test').to.have.ownProperty('length'); // throw 断言目标抛出特定的异常var err = new ReferenceError('This is a bad function.');  var fn = function () { throw err; }  expect(fn).to.throw(ReferenceError);  expect(fn).to.throw(Error);  expect(fn).to.throw(/bad function/);  expect(fn).to.not.throw('good function');  expect(fn).to.throw(ReferenceError, /bad function/);  expect(fn).to.throw(err);  expect(fn).to.not.throw(new RangeError('Out of range.'));  // satisfy(method) 断言目标通过一个真值测试expect(1).to.satisfy(function(num) { return num > 0; })

三. mocha测试代码如何运行?

上面的add.test.js 编写完成后,我们需要运行测试代码了,进入add.test.js代码的目录后,执行如下命令可运行:

mocha add.test.js

如下结果:

$ mocha add.test.js  加法函数的测试    ✓ 1加1应该等于2  1 passing (10ms)

如上所示,表示测试脚本通过了测试,共用一个测试用例,耗时10毫秒。

mocha命令后面也可以指定多个文件,如下命令:

mocha xx.test.js yy.test.js

3-1 把测试文件放入test目录下

mocha默认运行test子目录里面的测试脚本,我们一般情况下,可以把测试脚本放在test目录下,然后进入对应的目录,直接执行mocha命令即可:
请看demo2;
如下目录页面:

demo2   |---- src   |  |--- add.js   |  |--- multiple.js   |  |--- reduce.js   |---- test   |  |--- dir   |  | |--- multiple.test.js    |  |   |  |--- add.test.js

src/add.js 代码如下:

function add(x, y) {  return x + y;}module.exports = add;

src/multiple.js代码如下:

function multiply(x, y) {  return x * y;}module.exports = multiply;

src/reduce.js 代码如下:

function add(x, y) {  return x - y;}module.exports = add;

test/add.test.js代码如下:

var add = require('../src/add.js');var expect = require('chai').expect;describe('加法函数的测试', function() {  it('1 加 1 应该等于 2', function() {    expect(add(1, 1)).to.be.equal(2);  });  it('任何数加0应该等于自身', function() {    expect(add(1, 0)).to.be.equal(1);  });});

test/dir/multiple.test.js代码如下:

var multiply = require('../../src/multiply');var expect = require('chai').expect;describe('乘法函数的测试', function() {  it('1 乘 1 应该等于 1', function() {    expect(multiply(1, 1)).to.be.equal(1);  });})

当我在demo2项目目录下,运行 mocha 命令后,执行如下:

$ mocha  加法函数的测试    ✓ 1 加 1 应该等于 2    ✓ 任何数加0应该等于自身  2 passing (10ms)

我们可以看到,test子目录里面的测试脚本执行了,但是test目录下还有dir这样的目录里面的测试脚本文件并没有执行,所以我们可以得出一个结论是,mocha

命令只会执行test第一层目录下所有文件,并不能执行嵌套目录下的文件。
为了执行所有嵌套目录下的文件,我们可以 mocha命令后面加一个参数 --recursive 参数,如下命令:

$ mocha --recursive  加法函数的测试    ✓ 1 加 1 应该等于 2    ✓ 任何数加0应该等于自身  乘法函数的测试    ✓ 1 乘 1 应该等于 1  3 passing (11ms)

四. 理解使用通配符

命令行中测试脚本文件,可能会有多个脚本文件需要被测试,这时候我们可以使用通配符,来做批量操作。
比如我们在 demo2下新建spec目录,文件目录变成如下结构:

demo2   |---- src   |  |--- add.js   |  |--- multiple.js   |  |--- reduce.js   |---- test   |  |--- dir   |  | |--- multiple.test.js    |  |   |  |--- add.test.js   |   |----- spec   |  |--- add.js   |  |--- reduce.js

demo2/spec/add.js 代码如下:

var add = require('../src/add.js');var expect = require('chai').expect;describe('加法函数的测试', function() {  it('1 加 1 应该等于 2', function() {    expect(add(1, 1)).to.be.equal(2);  });  it('任何数加0应该等于自身', function() {    expect(add(1, 0)).to.be.equal(1);  });});

demo2/spec/reduce.js代码如下:

var reduce = require('../src/reduce.js');var expect = require('chai').expect;describe('减法函数的测试', function() {  it('2 减 1 应该等于 1', function() {    expect(reduce(2, 1)).to.be.equal(1);  });});

我们可以运行如下命令,执行多个测试脚本文件:

mocha spec/{add,reduce}.js

命令效果如下:

$ mocha spec/{add,reduce}.js  加法函数的测试    ✓ 1 加 1 应该等于 2    ✓ 任何数加0应该等于自身  减法函数的测试    ✓ 2 减 1 应该等于 1  3 passing (11ms)

或者直接后面加*号,匹配所有的文件,和js中的正则类似:如下命令:

$ mocha spec/*.js  加法函数的测试    ✓ 1 加 1 应该等于 2    ✓ 任何数加0应该等于自身  减法函数的测试    ✓ 2 减 1 应该等于 1  3 passing (10ms)

五. 命令行参数常用的有哪些?

5.1 --help
--help参数,用来查看Mocha的所有命令行参数,如下命令所示:
mocha --help

5.2 --reporter

--reporter参数用来指定测试报告的格式,默认是spec格式。

$ mocha

# 等同于
$ mocha --reporter spec

我们可以使用 mocha --reporters 命令查看所有内置的报告格式。如下命令:

$ mocha --reporters        dot - dot matrix    doc - html documentation    spec - hierarchical spec list    json - single json object    progress - progress bar    list - spec-style listing    tap - test-anything-protocol    landing - unicode landing strip    xunit - xunit reporter    min - minimal reporter (great with --watch)    json-stream - newline delimited json events    markdown - markdown documentation (github flavour)    nyan - nyan cat!

我们可以使用模块,可以生成漂亮的HTML格式的报告。

首先我们需要安装 mochawesome模块,如下命令行:

npm install --save-dev mochawesome
$ ../node_modules/.bin/mocha --reporter mochawesome  加法函数的测试    ✓ 1 加 1 应该等于 2    ✓ 任何数加0应该等于自身  2 passing (10ms)[mochawesome] Report JSON saved to /Users/tugenhua/个人demo/vue1204/mocha/demo2/mochawesome-report/mochawesome.json[mochawesome] Report HTML saved to /Users/tugenhua/个人demo/vue1204/mocha/demo2/mochawesome-report/mochawesome.html

因此会在demo2项目目录下生成 mochawesome-report 文件目录,我们可以查看 mochawesome/mochawesome.html文件打开看一下即可:

5.3 --watch

--watch 参数用来监听指定的测试脚本,只要测试脚本有变化,就会自动运行mocha。我们在demo2目录下,运行 mocha --watch命令,
然后修改脚本文件,可以看到如下:

$ mocha --watch  加法函数的测试    ✓ 1 加 1 应该等于 2    ✓ 任何数加0应该等于自身  2 passing (9ms)  加法函数的测试11    ✓ 1 加 1 应该等于 211    ✓ 任何数加0应该等于自身  2 passing (2ms)

我在add.js 加了一句 console.log(11),上面可以看到也同样重新执行了 mocha命令。

5.4 --bail

--bail参数指定只要有一个测试用例没有通过,就停止执行后面的测试用例。
mocha --bail

5.5 --grep

--grep参数用于搜索测试用例的名称(即it块的第一个参数),然后只执行到匹配的测试用例。
如下代码命令:

$ mocha                  加法函数的测试11    ✓ 1 加 1 应该等于 211    ✓ 任何数加0应该等于自身  2 passing (10ms)~/个人demo/vue1204/mocha/demo2 on  Dev_20171115_wealth!$ mocha --grep "1 加 1"  加法函数的测试11    ✓ 1 加 1 应该等于 2  1 passing (12ms)

5.6 --invert

--invert参数表示只运行不符合条件的测试脚本,必须与 --grep参数配合使用。
如下执行结果:

 

~/个人demo/vue1204/mocha/demo2 on  Dev_20171115_wealth! $ mocha                           加法函数的测试11    ✓ 1 加 1 应该等于 211    ✓ 任何数加0应该等于自身  2 passing (13ms)~/个人demo/vue1204/mocha/demo2 on  Dev_20171115_wealth! $ mocha --grep "1 加 1" --invert  加法函数的测试11    ✓ 任何数加0应该等于自身  1 passing (10ms)

六. 配置文件 mocha.opts

Mocha的测试脚本文件 允许放在test目录下面,但是我们也可以在test目录下新建一个mocha.opts文件,把命令行写在该里面,还是看demo2目录结构,
在test目录下新建 mocha.opts文件,如下目录结构:

demo2   |---- src   |  |--- add.js   |  |--- multiple.js   |  |--- reduce.js   |---- test   |  |--- dir   |  | |--- multiple.test.js    |  |   |  |--- add.test.js   |  |--- mocha.opts   |   |----- spec   |  |--- add.js   |  |--- reduce.js

mocha.opts文件写入如下命令:

--recursive--reporter tap

然后执行mocha命令,就可以执行测试中的所有测试代码:

~/个人demo/vue1204/mocha/demo2 on  Dev_20171115_wealth! $ mocha1..311ok 1 加法函数的测试 1 加 1 应该等于 211ok 2 加法函数的测试 任何数加0应该等于自身ok 3 乘法函数的测试 1 乘 1 应该等于 1# tests 3# pass 3# fail 0

当然如果测试用例不是存放在test子目录下,可以在mocha.opts写入如下内容:

server-tests--recursive--reporter tap

上面代码指定允许 server-tests 目录及其子目录之中的测试脚本。

七: ES6的测试;

如果测试脚本是用ES6编写的,那么允许测试之前,需要先用babel转码,我们在test目录下新建 es6.test.js文件,先看目录结构如下:

demo2   |---- src   |  |--- add.js   |  |--- multiple.js   |  |--- reduce.js   |---- test   |  |--- dir   |  | |--- multiple.test.js    |  |   |  |--- add.test.js   |  |--- es6.test.js   |  |--- mocha.opts   |   |----- spec   |  |--- add.js   |  |--- reduce.js

es6.test.js 代码如下:

import add from '../src/add.js';import chai from 'chai';let expect = chai.expect;describe('加法函数的测试', function() {  it('1 加 1 应该等于 2', function() {    expect(add(1, 1)).to.be.equal(2);  });  it('任何数加0应该等于自身', function() {    expect(add(1, 0)).to.be.equal(1);  });});

如果我们直接在demo2命令行中允许 mocha命令就会报错,如下报错:

$ mocha/Users/tugenhua/个人demo/vue1204/mocha/demo2/test/es6.test.js:1(function (exports, require, module, __filename, __dirname) { import add from '../src/add.js';                                                              ^^^^^^SyntaxError: Unexpected token import

因此我们需要ES6转码,需要安装Babel。命令如下:

npm install babel-core babel-preset-es2015 --save-dev

然后我们需要在项目的目录下,新建一个 .babelrc配置文件。

添加如下代码如下:

{  "presets": ['es2015']}

最后,我们使用 --compilers 参数指定测试脚本的转码器。

../node_modules/mocha/bin/mocha --compilers js:babel-core/register

如上命令代码,--compilers 参数后面是一个使用冒号分割的字符串,冒号左边是文件的后缀名,右边是用来处理这一类文件的模块名,意思是说,先使用

babel-core/register模块,处理一下 .js文件;如下命令行代码所示:

~/个人demo/vue1204/mocha/demo2 on  Dev_20171115_wealth! $ ../node_modules/mocha/bin/mocha --compilers js:babel-core/register1..5(node:55513) DeprecationWarning: "--compilers" will be removed in a future version of Mocha; see https://git.io/vdcSr for more info11ok 1 加法函数的测试 1 加 1 应该等于 211ok 2 加法函数的测试 任何数加0应该等于自身ok 3 乘法函数的测试 1 乘 1 应该等于 111ok 4 加法函数的测试 1 加 1 应该等于 211ok 5 加法函数的测试 任何数加0应该等于自身# tests 5# pass 5# fail 0

注意点:Babel默认不会对 Iterator, Generator, Promise, Map, Set等全局对象,以及一些全局对象的方法(比如Object.assign)转码,

如果我们想要对这些对象转码,我们需要安装 babel-polyfill.

npm install --save-dev babel-polyfill

最后,需要在我们的脚本头部加上 如下引入 babel-polyfill代码

import 'babel-polyfill'

八,异步测试

先在mocha项目目录下 新建文件demo3,如下目录结构:

demo3  |---- timeout.test.js

timeout.test.js代码如下:

var expect = require('chai').expect;describe('timeout.test.js - 超时测试', function() {  it('测试应该 5000 毫秒后结束', function(done) {    var x = true;    var f = function() {      x = false;      expect(x).to.be.not.ok;      done();    };    setTimeout(f, 4000);  });});

然后在demo3目录下,运行命令行 mocha timeout.test.js, 执行如下:

~/个人demo/vue1204/mocha/demo3 on  Dev_20171115_wealth!$ mocha timeout.test.js  timeout.test.js - 超时测试    1) 测试应该 5000 毫秒后结束  0 passing (2s)  1 failing  1) timeout.test.js - 超时测试       测试应该 5000 毫秒后结束:     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

可以看到如上报错 Timeout of 2000ms exceeded, 这是因为mocha默认每个测试用例最多执行2000毫秒,如果超过这个时间没有返回结果,就会报错,

所以我们在进行异步操作的时候,需要额外指定timeout的时间的。因为异步的操作是需要4000毫秒,所以我们指定5000毫秒就不会报错了。
如下命令:

mocha --timeout 5000 timeout.test.js

如下执行结果:

~/个人demo/vue1204/mocha/demo3 on  Dev_20171115_wealth! $ mocha --timeout 5000 timeout.test.js  timeout.test.js - 超时测试    ✓ 测试应该 5000 毫秒后结束 (4008ms)  1 passing (4s)

这样就保证测试用例成功了。

Mocha内置对Promise的支持,允许直接返回Promise. 在demo3目录下 新建 promise.test.js, 如下目录结构:

demo3  |---- timeout.test.js  |---- promise.test.js

promise.test.js 代码如下:

var fetch = require('node-fetch');var expect = require('chai').expect;describe('promise异步测试', function() {  it('异步请求应该返回一个对象', function() {    return fetch("https://api.github.com")      .then(function(res) {        return res.json()      }).then(function(json) {        expect(json).to.be.an("object");      })  })});

然后执行命令如下:

~/个人demo/vue1204/mocha/demo3 on  Dev_20171115_wealth!$ mocha promise.test.js  promise异步测试    ✓ 异步请求应该返回一个对象 (1165ms)  1 passing (1s)

如上可以看到也是可以成功的。

九:测试用例的钩子

Mocha在describe块之中,提供了测试用例的四个钩子,before(), after(), beforeEach()和afterEach(),他们会在指定的时间内执行。

代码如下:

describe('hooks', function() {  before(function(){    // 在本区块的所有测试用例之前执行  });  after(function(){    // 在本区块的所有测试用例之后执行  });  beforeEach(function(){    // 在本区块的每个测试用例之前执行  });  afterEach(function(){    // 在本区块的每个测试用例之后执行  });});

before(): 将会在所有测试用例执行之前运行,比如在之前插入数据等等操作。

after(): 会在所有测试执行之后运行,用于清理测试环境,回滚到清空数据状态。
beforeEach(): 将会在每个测试用例执行之前执行,可用于测试测试需要准备相关数据的条件。
afterEach(): 将会在每个测试用例之后执行,可用于准备测试用例所需的后置条件。
请看如下demo,在来理解下 mocha的四个钩子函数,
在项目的根目录下 新建demo4,目录结构如下:

demo4  |---- src  |  |-- hooks.js  |---- test  |  |--- hooks.test.js

hooks.js 代码如下:

// 保存用户对象var saveUserObj = {};// 定义用户类function User (name) {}// 保存用户User.save = function(name) {  saveUserObj[name] = name;} // 删除用户User.delete = function(name) {  delete saveUserObj[name];}// 检查是否包含该用户User.contains = function(name) {  return saveUserObj[name] !== null;}// 返回所有的数据User.getUsers = function() {  return saveUserObj;}module.exports = User;

hooks.test.js代码如下:

var should = require('should');var User = require('../src/hooks.js');// 描述User的行为describe('描述User的行为', function(){  // 执行所有测试之前,执行before函数,添加数据  before(function(){    User.save('kongzhi111');    console.log(User.getUsers()); // 打印出{kongzhi111: 'kongzhi111'}    console.log(111111111111111111111);  });  // 在执行每个测试前,执行beforeEach函数,添加数据  beforeEach(function() {    User.save('kongzhi222');    console.log(User.getUsers());    // 打印出 {kongzhi111: 'kongzhi111', kongzhi222: 'kongzhi222'}    console.log(222222222222222222222222)  })  // 描述User.save的行为  describe('描述User.save的行为', function() {    // 保存kongzhi333成功了    it('保存kongzhi333成功了', function() {      User.save('kongzhi333');      console.log(User.getUsers());      // 打印出 {kongzhi111: 'kongzhi111', kongzhi222: 'kongzhi222', kongzhi333: 'kongzhi333'}      console.log(33333333333333333333);    })  });  // 描述User.contains的行为  describe('描述User.contains的行为', function(){    it('kongzhi111是存在的', function(){      User.contains('kongzhi111').should.be.exactly(true);    });    it('kongzhi222是存在的', function(){      User.contains('kongzhi222').should.be.exactly(true);    });    it('kongzhi333是存在的', function(){      User.contains('kongzhi333').should.be.exactly(true);    });    it('kongzhi555是不存在', function(){      User.contains('kongzhi555').should.be.exactly(true);    });  });  // 在执行完每个测试后,清空数据  afterEach(function() {    User.delete('kongzhi222');    console.log(User.getUsers());  // 打印 {kongzhi111: 'kongzhi111', kongzhi333: 'kongzhi333'}    console.log(44444444444444444444444);  });  // 在执行完每个测试后,清空数据  after(function() {    User.delete('kongzhi111');    console.log(User.getUsers()); // 打印 {kongzhi333: 'kongzhi333'}    console.log(555555555555555555555555);    User.delete('kongzhi333');    console.log(User.getUsers()); // 打印 {}  });})

在demo4下 运行mocha,执行命令后 如下:

~/个人demo/vue1204/mocha/demo4 on  Dev_20171115_wealth!$ mocha   描述User的行为{ kongzhi111: 'kongzhi111' }111111111111111110000    描述User.save的行为{ kongzhi111: 'kongzhi111', kongzhi222: 'kongzhi222' }2.2222222222222222e+23{ kongzhi111: 'kongzhi111',  kongzhi222: 'kongzhi222',  kongzhi333: 'kongzhi333' }33333333333333330000      ✓ 保存kongzhi333成功了{ kongzhi111: 'kongzhi111', kongzhi333: 'kongzhi333' }4.4444444444444445e+22    描述User.contains的行为{ kongzhi111: 'kongzhi111',  kongzhi333: 'kongzhi333',  kongzhi222: 'kongzhi222' }2.2222222222222222e+23      ✓ kongzhi111是存在的{ kongzhi111: 'kongzhi111', kongzhi333: 'kongzhi333' }4.4444444444444445e+22{ kongzhi111: 'kongzhi111',  kongzhi333: 'kongzhi333',  kongzhi222: 'kongzhi222' }2.2222222222222222e+23      ✓ kongzhi222是存在的{ kongzhi111: 'kongzhi111', kongzhi333: 'kongzhi333' }4.4444444444444445e+22{ kongzhi111: 'kongzhi111',  kongzhi333: 'kongzhi333',  kongzhi222: 'kongzhi222' }2.2222222222222222e+23      ✓ kongzhi333是存在的{ kongzhi111: 'kongzhi111', kongzhi333: 'kongzhi333' }4.4444444444444445e+22{ kongzhi111: 'kongzhi111',  kongzhi333: 'kongzhi333',  kongzhi222: 'kongzhi222' }2.2222222222222222e+23      ✓ kongzhi555是不存在{ kongzhi111: 'kongzhi111', kongzhi333: 'kongzhi333' }4.4444444444444445e+22{ kongzhi333: 'kongzhi333' }5.5555555555555555e+23{}

可以看到如上测试结果后的运行,试着理解一下,应该可以理解mocha中的4各钩子函数的含义了。

理解异步钩子函数

在demo4目录下的test文件下 新建 hooks-async.test.js 用于测试异步的代码

demo4  |---- src  |  |-- hooks.js  |---- test  |  |--- hooks.test.js  |  |--- hooks-async.test.js

hooks-async.test.js 代码如下:

var expect = require('chai').expect;describe('异步钩子函数', function() {  var foo = false;  beforeEach(function(){    setTimeout(function(){      foo = true;    }, 50)  });  it('异步钩子函数成功', function() {    expect(foo).to.be.equal(true);  })});

运行结果如下:

异步钩子函数       异步钩子函数成功:      AssertionError: expected false to equal true      + expected - actual      -false      +true

如上可以看到测试失败,原因是因为setTimeout 是异步的,在setTimeout执行完之前,it函数已经被执行了,所以foo当时数据还是false,

因此false不等于true了。

这时候 done参数出来了,在回调函数存在时候,它会告诉mocha,你正在编写一个异步测试,会等到异步测试完成的时候来调用done函数。

或者超过2秒后超时,如下代码就可以成功了;
hooks-async.test.js 代码如下:

var expect = require('chai').expect;describe('异步钩子函数', function() {  var foo = false;  beforeEach(function(done){    setTimeout(function(){      foo = true;      // complete the async beforeEach      done();    }, 50)  });  it('异步钩子函数成功', function() {    expect(foo).to.be.equal(true);  });});

10. 理解测试用例的管理

一个脚本中可能有很多测试用例,有时候,我们想只运行其中的几个,这时候我们使用only方法。describe块和it块都允许调用only方法,
表示只运行某个测试套件或测试用例。
在项目中新建文件demo5,结构如下:

demo5  |---- src  |  |-- add.js  |---- test  |  |--- add.test.js

add.test.js 代码如下:

var expect = require('chai').expect;var add = require('../src/add.js');it.only('1 加 1应该等于2', function() {  expect(add(1, 1)).to.be.equal(2);});it('任何数加0应该等于自身', function() {  expect(add(1, 0)).to.be.equal(1);});

进入demo5目录,运行mocha命令后,如下:

~/个人demo/vue1204/mocha/demo5 on  Dev_20171115_wealth!$ mocha  ✓ 1 加 1应该等于2  1 passing (8ms)

可以看到只运行了 only方法。

十一:浏览器测试

除了在命令行运行,mocha还可以在浏览器下运行。
首先,使用 mocha init 命令在在指定的目录生成初始化文件。
mocha init demo6
在mocha目录下 运行上面的命令后,会在demo6生成 index.html. mocha.css, mocha.js 和 tests.js 文件。
index.html代码如下:

      Mocha    

然后在demo6 下 新建一个 src/add.js 文件

代码如下:

function add(x, y) {  return x + y;}

然后,把这个文件,以及断言库chai.js,加入index.html。

代码如下:

      Mocha    

然后在 tests.js 添加如下代码:

var expect = chai.expect;describe('加法函数的测试', function() {  it('1 加 1 应该等于 2', function() {    expect(add(1, 1)).to.be.equal(2);  });  it('任何数加0等于自身', function() {    expect(add(1, 0)).to.be.equal(1);    expect(add(0, 0)).to.be.equal(0);  });});

运行index.html 即可看到效果。

十二: 生成规格文件

Mocha支持从测试用例生成规格文件。
在mocha-demo项目内 新建demo7文件,该目录文件存放如下文件
如下目录页面:

demo7   |---- src   |  |--- add.js   |  |--- multiple.js   |---- test   |  |--- dir   |  | |--- multiple.test.js    |  |   |  |--- add.test.js

进入demo7目录,运行如下命令:

$ mocha --recursive -R markdown >spec.md

就会在该目录下 生成 spec.md 文件,-R markdown参数指定规格报告是markdown格式。

如果想生成HTML格式的报告spec.html,使用下面的命令。

$ mocha --recursive -R doc > spec.html

就会在该目录下 生成 spec.html文件。

转载于:https://www.cnblogs.com/tugenhua0707/p/8419534.html

你可能感兴趣的文章
用OGRE1.74搭建游戏框架(三)--加入人物控制和场景
查看>>
转化课-计算机基础及上网过程
查看>>
android dialog使用自定义布局 设置窗体大小位置
查看>>
ionic2+ 基础
查看>>
互联网模式下我们更加应该“专注”
查看>>
myeclipse集成jdk、tomcat8、maven、svn
查看>>
查询消除重复行
查看>>
Win 10 文件浏览器无法打开
查看>>
HDU 1212 Big Number(C++ 大数取模)(java 大数类运用)
查看>>
-bash: xx: command not found 在有yum源情况下处理
查看>>
[leetcode]Minimum Path Sum
查看>>
内存管理 浅析 内存管理/内存优化技巧
查看>>
hiho1079 线段树区间改动离散化
查看>>
【BZOJ 5222】[Lydsy2017省队十连测]怪题
查看>>
第二次作业
查看>>
【input】 失去焦点时 显示默认值 focus blur ★★★★★
查看>>
Java跟Javac,package与import
查看>>
day-12 python实现简单线性回归和多元线性回归算法
查看>>
Json格式的字符串转换为正常显示的日期格式
查看>>
[转]使用 Razor 进行递归操作
查看>>