javascript单元测试框架mochajs详解

2016-08-03 09:41 邹成卓 Share this on Facebook 点击报名

  对于一些比较重要的项目,每次更新代码之后总是要自己测好久,担心一旦上线出了问题影响的服务太多,此时就希望能有一个比较规范的测试流程。在github上看到牛逼的javascript开源项目,也都是有测试代码的,看来业界大牛们都比较注重单元测试这块。

  就我自己的理解而言:

  涉及到大量业务逻辑的代码,可能我没有精力去给每个函数都写上单元测试的代码,功能细节的测试应该交由测试的同事去完成,但是对会直接影响项目正常运行的重要的数据接口,还是可以看情况写上几个单元测试用例的,每一次修改之后跑一跑用例测试一下。

  重要的框架底层模块,任何地方出一个小问题,都可能影响到很多服务。对于这种模块,最好是每个函数、每种接口都写上单元测试代码,不然一出问题就是一个大坑啊。

  开放出去的公共模块,可以针对主要的函数和接口写上单元测试代码,这样可以确保模块代码比较健壮,看起来也专业一些:)。

  基于以上几个想法,我决定学习一款Javascript单元测试框架,并试试去使用它写一些单元测试的代码。

  看了很多技术站点和博客的文章,参考了一部分开源项目的测试代码,大致观望下风向,决定学习一下mocha.js这款单元测试框架。

  别人的文章都是别人自己学习、咀嚼理解出来的内容,想学的透彻一点,还是自己学习并翻译一遍原版官方的文档比较好。

  mocha单元测试框架简介

  mocha是一款功能丰富的javascript单元测试框架,它既可以运行在nodejs环境中,也可以运行在浏览器环境中。

  javascript是一门单线程语言,最显著的特点就是有很多异步执行。同步代码的测试比较简单,直接判断函数的返回值是否符合预期就行了,而异步的函数,就需要测试框架支持回调、promise或其他的方式来判断测试结果的正确性了。mocha可以良好的支持javascript异步的单元测试。

  mocha会串行地执行我们编写的测试用例,可以在将未捕获异常指向对应用例的同时,保证输出灵活准确的测试结果报告。

  安装mocha

  npm install mocha -g

  一个简单的例子

  全局安装mocha后,在项目根目录创建test目录

  编写 test01.js ,

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

  describe('Array', function() {

  describe('#indexOf()', function() {

  it('should return -1 when the value is not present', function() {

  assert.equal(-1, [1,2,3].indexOf(5));

  assert.equal(-1, [1,2,3].indexOf(0));

  });

  });

  });

  npm install chai --save 安装一下官方文档中使用的chai断言模块(一个用来判断结果是否正确的模块)

  打开控制台,在test目录同级运行 mocha ,得到如下结果:

  Array

  #indexOf()

  √ should return -1 when the value is not present

  1 passing (11ms)

  可以看到:

  describe函数的第一个参数会被输出在控制台中,作为一个用例集的描述,而且这个描述是可以根据自己的需求来嵌套输出的,下面称之为: 用例集定义函数 。

  it函数第一个参数用来输出一个用例的描述,前边打个对勾代表测试通过,第二个参数是一个函数,用来编写用例内容,用断言模块来判断结果的正确性,下面称之为 用例函数 。

  mocha支持的断言模块

  mocha支持任何可以抛出一个错误的断言模块。例如:should.js、better-assert、expect.js、unexpected、chai等。这些断言库各有各的特点,大家可以了解一下它们的特点,根据使用场景来选择断言库。

  同步代码测试

  在测试同步代码的时候,用例函数执行完毕后,mocha就直接开始执行下一个用例函数了。 下面是一个同步测试代码的例子:

  describe('Array', function() {

  describe('#indexOf()', function() {

  it('should return -1 when the value is not present', function() {

  [1,2,3].indexOf(5).should.equal(-1);

  [1,2,3].indexOf(0).should.equal(-1);

  });

  });

  });

  异步代码测试

  官方文档自称,用mocha来测试异步的代码不要再简单!真的很自信啊~~

  只需要在用例函数里边加一个done回调,异步代码执行完毕后调用一下done,就可以通知mocha,我执行完啦,去执行下一个用例函数吧!

  就像下面这样:

  describe('User', function() {

  describe('#save()', function() {

  it('should save without error', function(done) {

  var user = new User('Luna');

  user.save(function(err) {

  if (err) throw err;

  done();

  });

  });

  });

  });

  对于上面的情况,判断用例执行成功与否是在异步代码的回调里边完成的,这种情况适用于正确性判断比较复杂的情况。如果异步代码中逻辑错误时,会在回调中抛出一个错误,那么测试代码还可以再简单一点:

  describe('User', function() {

  describe('#save()', function() {

  it('should save without error', function(done) {

  var user = new User('Luna');

  user.save(function(err) {

  if (err) throw err;

  done();

  });

  });

  });

  });

  promise代码测试

  如果异步模块并不是使用callback,而是使用promise来返回结果的时候,可以让用例函数返回一个promise对象来进行正确性判断,像下面这样:

  beforeEach(function() {

  return db.clear()

  .then(function() {

  return db.save([tobi, loki, jane]);

  });

  });

  describe('#find()', function() {

  it('respond with matching records', function() {

  return db.find({ type: 'User' }).should.eventually.have.length(3);

  });

  });

  后边还会再提到这种情况

  不建议使用箭头函数

  不建议在mocha测试框架中使用箭头函数。箭头函数语法中对this的绑定让会用例函数没办法访问Mocha框架上下文中定义的一些函数,例如 this.timeout(1000) 在箭头函数中就无法得到正确的结果。

  我对这里的理解是:mocha会把用例函数注册到自身的某个属性中,通过属性调用的使用,正常函数可以访问到mocha的其他属性,但是箭头函数不行,就像下面的代码一样:

  function getTest(){

  this.a=555;

  var test={

  a:1,

  b:function(){

  console.log(this.a)

  },

  c:()=>{

  console.log(this.a);

  }

  }

  return test;

  }

  var test=getTest();

  test.b();

  test.c();

  输出结果是

  1

  555

  钩子函数

  mocha提供4种钩子函数: before() 、 after() 、 beforeEach() 、 afterEach() ,这些钩子函数可以用来在用例集/用例函数开始执行之前/结束执行之后,进行一些环境准备或者环境清理的工作。

  describe('hooks', function() {

  before(function() {

  // runs before all tests in this block

  });

  after(function() {

  // runs after all tests in this block

  });

  beforeEach(function() {

  // runs before each test in this block

  });

  afterEach(function() {

  // runs after each test in this block

  });

  // test cases

  });

  钩子函数的描述参数

  定义钩子函数的时候,可以传第一个可选参数作为钩子函数的描述,可以帮助定位用例中的错误信息。若没有穿第一个参数,使用一个非匿名函数作为钩子函数,那么函数名称就将被作为钩子函数的描述。

  beforeEach(function() {

  // beforeEach hook

  });

  beforeEach(function namedFun() {

  // beforeEach:namedFun

  });

  beforeEach('some description', function() {

  // beforeEach:some description

  });

  异步的钩子函数

  钩子函数不仅能是同步函数,也可能是异步的函数,就像前边的异步测试用例函数一样。如果我们在开始之前,需要做一些异步的操作,例如在数据库里边准备一些模拟数据,就需要用到这种场景了:

  describe('Connection', function() {

  var db = new Connection,

  tobi = new User('tobi'),

  loki = new User('loki'),

  jane = new User('jane');

  beforeEach(function(done) {

  db.clear(function(err) {

  if (err) return done(err);

  db.save([tobi, loki, jane], done);

  });

  });

  describe('#find()', function() {

  it('respond with matching records', function(done) {

  db.find({type: 'User'}, function(err, res) {

  if (err) return done(err);

  res.should.have.length(3);

  done();

  });

  });

  });

  });

  全局钩子

  前边讲的钩子函数都是定义在用例集函数里边的,如果在用例集函数之外定义钩子函数,那么这个钩子函数将会对所有的mocha单元测试用例生效。若编写了多个用例集js文件,无论在哪一个用例集文件中,用例集函数之外定义钩子函数,都会对所有用例函数生效。

  前边讲到,用例集函数是可以嵌套的,而mocha会生成一个包在最外面的describe函数,把所有的用例集包含起来,那么在其中定义的钩子函数也就对所有的用例函数生效了~

  beforeEach(function() {

  console.log('before every test in every file');

  });

  延迟启动测试

  如果想在mocha命令运行之后,先做一些别的工作,再启动测试,可以使用 mocha --delay 命令,此命令会在全局环境中生成一个run函数,延迟工作完成后调用run函数即可启动测试。

  setTimeout(function() {

  // do some setup

  describe('my suite', function() {

  // ...

  });

  run();

  }, 5000);

  测试用例TODO

  可以编写一个等待被实现的测试用例,在报告里边也会有提示

  describe('Array', function() {

  describe('#indexOf()', function() {

  // pending test below

  it('should return -1 when the value is not present');

  });

  });

  2 passing (11ms)

  1 pending

  仅执行一个用例集/用例

  在用例集函数或者用例函数后边添加 .only() 可以让mocha只执行此用例集或用例

  describe('Array', function() {

  describe.only('#indexOf()', function() {

  // ...

  });

  });

  Array用例集下面的嵌套集合,只有#indexOf用例集会被执行

  describe('Array', function() {

  describe('#indexOf()', function() {

  it.only('should return -1 unless present', function() {

  // ...

  });

  it('should return the index when present', function() {

  // ...

  });

  });

  });

  这种写法,#indexOf用例集下面的用例,只有第一个加了only的会被执行。

  注意:在同一用例集下有多个only标记,mocha会报错。

  跳过哪些用例集/用例

  和加上.only相反,在用例集函数或者用例函数后边加 .skip() ,可以跳过此用例集或用例的执行。跳过的用例会被标记为 pending 的用例,在报告中也会作为pending用例体现出来。下面是一些例子:

  describe('Array', function() {

  describe.skip('#indexOf()', function() {

  // ...

  });

  });

  跳过用例集

  describe('Array', function() {

  describe('#indexOf()', function() {

  it.skip('should return -1 unless present', function() {

  // ...

  });

  it('should return the index when present', function() {

  // ...

  });

  });

  });

  跳过用例。

  对于一些作废的用例,按我们以往的做法可能就是把它注释掉,mocha推荐的做法是给它们加上skip标记。

  除了使用添加skip标记之外,mocha还允许在用例执行的过程中跳过此用例,例如用例执行需要某些上下文环境,但是执行的时候发现这些环境并没有准备好,此时就可以调用skip函数跳过此用例:

  it('should only test in the correct environment', function() {

  if (/* check test environment */) {

  // make assertions

  } else {

  this.skip();

  }

  });

  上面被跳过的用例同样会在测试报告中以pending的形式体现出来。为了避免测试逻辑混乱,在调用skip函数之后,就不要再再用例函数或after钩子中执行更多的逻辑了。

  这里要说明一点,在一个用例函数中,不要存在一个逻辑分支啥也不做,直接让整个用例函数结束,这样是不科学的。用例函数中应该至少使用断言做一个判断,或者调用skip函数跳过用例。

  it('should only test in the correct environment', function() {

  if (/* check test environment */) {

  // make assertions

  } else {

  // do nothing

  }

  });

  这样的用例如果走到了do nothing逻辑,在报告中会被标记为pass。比较推荐的做法是,在before钩子函数中检查测试需要的上下文环境,不具备则跳过。

  before(function() {

  if (/* check test environment */) {

  // setup code

  } else {

  this.skip();

  }

  });

  重新执行用例

  你可以指定让一个失败的用例重新执行一定次数。这个特性是为做 end-to-end测试 (功能性测试/Selenium测试)而设计的,这些测试数据不好模拟。 mocha是不推荐用这个特性来做单元测试的。

  这个特性会重新运行用例函数的beforeEach和afterEach钩子函数,但是不会重新运行before和after钩子函数。

  下面是一个重新执行的例子:

  describe('retries', function() {

  // Retry all tests in this suite up to 4 times

  this.retries(4);

  beforeEach(function () {

  browser.get('http://www.yahoo.com');

  });

  it('should succeed on the 3rd try', function () {

  // Specify this test to only retry up to 2 times

  this.retries(2);

  expect($('.foo').isDisplayed()).to.eventually.be.true;

  });

  });

  动态生成用例

  mocha可以使用 Function.prototype.call 和函数表达式来定义用例集和用例,它们可以用来直接动态生成一些测试用例,而不需要使用其他额外的语法。

  和你可能在其他框架中见到的一样,这个特性可以实现通过定义一些参数来实现测试用例的功能。

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

  function add() {

  return Array.prototype.slice.call(arguments).reduce(function(prev, curr) {

  return prev + curr;

  }, 0);

  }

  describe('add()', function() {

  var tests = [

  {args: [1, 2], expected: 3},

  {args: [1, 2, 3], expected: 6},

  {args: [1, 2, 3, 4], expected: 10}

  ];

  tests.forEach(function(test) {

  it('correctly adds ' + test.args.length + ' args', function() {

  var res = add.apply(null, test.args);

  assert.equal(res, test.expected);

  });

  });

  });

  上面的测试会生成下面这样报告:

  add()

  ? correctly adds 2 args

  ? correctly adds 3 args

  ? correctly adds 4 args

  测试时间

  许多测试报告会展示测试时间,同样也会标记出那些用例耗时比较长:

  可能对于某些测试用例,耗时就是会比较长,那么耗费多长时间才应该本认为执行耗时过长呢? 可以通过 slow() 函数来标记一下:

  describe('something slow', function() {

  this.slow(10000);

  it('should take long enough for me to go make a sandwich', function() {

  // ...

  });

  });

  测试超时

  用例集执行超时

  在用例集下定义的timeout超时会对此用例集下定义的所有嵌套的用例集和用例生效,如果嵌套的用例集或者用例重写了timeout时间,则会覆盖上层的设置。通过 this.timeout(0) ,可以关掉用例或用例集的超时判断。

  describe('a suite of tests', function() {

  this.timeout(500);

  it('should take less than 500ms', function(done){

  setTimeout(done, 300);

  });

  it('should take less than 500ms as well', function(done){

  setTimeout(done, 250);

  });

  })

  用例执行超时

  it('should take less than 500ms', function(done){

  this.timeout(500);

  setTimeout(done, 300);

  });

  钩子函数超时

  describe('a suite of tests', function() {

  beforeEach(function(done) {

  this.timeout(3000); // A very long environment setup.

  setTimeout(done, 2500);

  });

  });

  钩子函数同样可以通过 this.timeout(0) 来关闭超时判断。

  diff差异比较功能

  若断言库抛出了AssertionErrors,且错误对象中有err.expected属性和err.actual属性,mocha会尝试在报告中展示期望的值和得到的值的差异:

  mocha使用命令和参数

  mocha init 初始化浏览器中测试

  mocha init 命令用来生成一个浏览器中单元测试的架子。

  新建一个目录test

  在同级目录运行命令 mocha init test ,可以看到test目录下生成了一些样式表文件和js脚本,以及一个用来运行用例、展示报告的index.html

  接着使用文章开头的chai断言库,此时需要用script标签引入了,于是在index.html中加上

  

  index.html内容如下:

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  test.js是一个空文件,等待我们去编写用例,在其中加上:

  var assert = chai.assert;

  describe('Array', function() {

  describe('#indexOf()', function() {

  it('should return -1 when the value is not present', function() {

  assert.equal(-1, [1,2,3].indexOf(5));

  assert.equal(-1, [1,2,3].indexOf(0));

  });

  });

  });

  在浏览器中打开index.html,可以看到用例执行报告:

  mocha命令参数

  mocha命令的基本格式是: mocha [debug] [options] [files]

  options包括下面这些,我翻译了一部分目前能理解的

  -h, --help 输出帮助信息

  -V, --version 输出mucha版本

  -A, --async-only 强制让所有测试用例必须使用callback或者返回promise的方式来异步判断正确性

  -c, --colors 启用报告中颜色

  -C, --no-colors 禁用报告中颜色

  -G, --growl enable growl notification support

  -O, --reporter-options reporter-specific options

  -R, --reporter specify the reporter to use

  -S, --sort 排序测试文件

  -b, --bail bail after first test failure

  -d, --debug enable node's debugger, synonym for node --debug

  -g, --grep 只执行满足 格式的用例

  -f, --fgrep 只执行含有 的用例

  -gc, --expose-gc 展示gc回收的log

  -i, --invert 让 --grep 和 --fgrep 的匹配取反

  -r, --require require一下指定的模块

  -s, --slow 指定slow时间(单位ms,默认75ms)

  -t, --timeout 指定超时时间(单位ms,默认2000ms)

  -u, --ui 指定user-interface (bdd|tdd|exports)

  -w, --watch 观察用例文件变化,并重新执行

  --check-leaks 检测未回收global变量泄露

  --compilers :,... 用指定的模块来编译文件

  --debug-brk 启用node的debug模式

  --delay 等待异步的用例集(见前边的)

  --es_staging enable all staged features

  --full-trace display the full stack trace

  --globals allow the given comma-delimited global [names]

  --harmony enable all harmony features (except typeof)

  --harmony-collections enable harmony collections (sets, maps, and weak maps)

  --harmony-generators enable harmony generators

  --harmony-proxies enable harmony proxies

  --harmony_arrow_functions enable "harmony arrow functions" (iojs)

  --harmony_classes enable "harmony classes" (iojs)

  --harmony_proxies enable "harmony proxies" (iojs)

  --harmony_shipping enable all shipped harmony features (iojs)

  --inline-diffs 显示预期和实际结果的string差异比较

  --interfaces display available interfaces

  --no-deprecation silence deprecation warnings

  --no-exit require a clean shutdown of the event loop: mocha will not call process.exit

  --no-timeouts 禁用timeout,可通过--debug隐式指定

  --opts 定义option文件路径

  --prof 显示统计信息

  --recursive 包含子目录

  --reporters 展示可用报告

  --retries 设置失败用例重试次数

  --throw-deprecation 每次调用deprecated函数的时候都抛出一个异常

  --trace 显示函数调用栈

  --trace-deprecation 启用的时候显示调用栈

  --watch-extensions ,... --watch监控的扩展

  下面是官方文档对部分命令的详细说明:

  -W, –WATCH

  用例一旦更新立即执行

  –COMPILERS

  例如 --compilers coffee:coffee-script 编译CoffeeScript 1.6,或者 --compilers coffee:coffee-script/register 编译CoffeeScript 1.7+

  -B, –BAIL

  如果只对第一个抛出的异常感兴趣,可以使用此命令。

  -D, –DEBUG

  开启nodejs的debug模式,可以在debugger语句处暂停执行。

  –GLOBALS

  names是一个以逗号分隔的列表,如果你的模块需要暴露出一些全局的变量,可以使用此命令,例如 mocha --globals app,YUI 。

  这个命令还可以接受通配符,例如 --globals '*bar 。参数传入 * 的话,会忽略所有全局变量。

  –CHECK-LEAKS

  默认情况下,mocha并不会去检查应用暴露出来的全局变量,加上这个配置后就会去检查,此时某全局变量如果没有用上面的–GLOBALS去配置为可接受,mocha就会报错

  -R, –REQUIRE

  这个命令可以用来引入一些依赖的模块,比如should.js等,这个命令相当于在测试目录下每个js文件头部运行一下 require('should.js') ,模块中对Object、Array等对象的扩展会生效,也可以用 --require ./test/helper.js 这样的命令去引入指定的本地模块。

  但是… 很鸡肋的是,如果要引用模块导出的对象,还是需要require, var should = require('should') 这样搞。

  -U, –UI

  –ui选项可以用来指定所使用的测试接口,默认是“bdd”

  -R, –REPORTER

  这个命令可以用来指定报告格式,默认是“spec”。可以使用第三方的报告样式,例如:

  npm install mocha-lcov-reporter , --reporter mocha-lcov-reporter

  -T, –TIMEOUT

  用来指定用例超时时间

  -S, –SLOW

  用来指定慢用例判定时间,默认是75ms

  -G, –GREP

  grep pattern可以用来筛选要执行的用例或用例集,pattern参数在mocha内部会被编译成一个正则表达式。

  假如有下面的测试用例:

  describe('api', function() {

  describe('GET /api/users', function() {

  it('respond with an array of users', function() {

  // ...

  });

  });

  });

  describe('app', function() {

  describe('GET /users', function() {

  it('respond with an array of users', function() {

  // ...

  });

  });

  });

  可以用 --grep api 、 --grep app 、 --grep users 、 --grep GET ,来筛选出要执行的用例。

  测试接口类型

  mocha的测试接口类型指的是集中测试用例组织模式的选择,包括BDD行为驱动开发(Behavior Driven Development),TDD测试驱动开发(Test-Driven Development),Exports,QUnit 和 Require-style 几种。

  BDD

  BDD测试接口提供 describe(), context(), it(), specify(), before(), after(), beforeEach(), 和 afterEach()几种函数,其中context函数只是describe函数的别名,specify函数也是if函数的别名。

  mocha默认的测试接口,前边的所有例子都是基于BDD来编写的。

  describe('Array', function() {

  before(function() {

  // ...

  });

  describe('#indexOf()', function() {

  context('when not present', function() {

  it('should not throw an error', function() {

  (function() {

  [1,2,3].indexOf(4);

  }).should.not.throw();

  });

  it('should return -1', function() {

  [1,2,3].indexOf(4).should.equal(-1);

  });

  });

  context('when present', function() {

  it('should return the index where the element first appears in the array', function() {

  [1,2,3].indexOf(3).should.equal(2);

  });

  });

  });

  });

  TDD

  TDD接口提供 suite(), test(), suiteSetup(), suiteTeardown(), setup(), 和 teardown()函数,用例写法如下:

  suite('Array', function() {

  setup(function() {

  // ...

  });

  suite('#indexOf()', function() {

  test('should return -1 when not present', function() {

  assert.equal(-1, [1,2,3].indexOf(4));

  });

  });

  });

  EXPORTS

  Exports 的写法有的类似于Mocha的前身expresso,其写法如下:

  module.exports = {

  before: function() {

  // ...

  },

  'Array': {

  '#indexOf()': {

  'should return -1 when not present': function() {

  [1,2,3].indexOf(4).should.equal(-1);

  }

  }

  }

  };

  通过exports导出的对象里边,除了几个钩子函数之外,其他的Object类型属性都是用例集,function类型的属性都是用例。

  QUNIT

  像TDD接口一样支持suite和test函数,同时又像BDD一样支持before(), after(), beforeEach(), 和 afterEach(),等钩子函数。

  function ok(expr, msg) {

  if (!expr) throw new Error(msg);

  }

  suite('Array');

  test('#length', function() {

  var arr = [1,2,3];

  ok(arr.length == 3);

  });

  test('#indexOf()', function() {

  var arr = [1,2,3];

  ok(arr.indexOf(1) == 0);

  ok(arr.indexOf(2) == 1);

  ok(arr.indexOf(3) == 2);

  });

  suite('String');

  test('#length', function() {

  ok('foo'.length == 3);

  });

  REQUIRE

  require测试接口允许你通过require来导入describe函数,取个任意的别名。如果你不希望测试中出现全局的变量,这个接口也是十分有用的。

  值得注意的是,这里的require不能直接通过node命令来执行,node的模块管理是不能解析这里的require的,需要通过mocha命令来运行。

  ar testCase = require('mocha').describe;

  var pre = require('mocha').before;

  var assertions = require('mocha').it;

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

  testCase('Array', function() {

  pre(function() {

  // ...

  });

  testCase('#indexOf()', function() {

  assertions('should return -1 when not present', function() {

  assert.equal([1,2,3].indexOf(4), -1);

  });

  });

  });

  测试报告视图

  如果不自己加上自定义的报告输出,mocha会在控制台中输出报告。

  SPEC视图

  这个是默认的报告样式,输出一个嵌套的分级视图

  DOT MATRIX视图

  用一系列点点来表示用例,测试的是红点,未实现的是蓝点,比较慢的是黄点,通过的是白点,如果你想让报告看起来简洁一些,可以用这个视图。

  NYAN视图

  尼玛这是个毛线视图啊,官方文档都懒得给出说明

  TAP视图

  LANDING STRIP视图

  ‘Landing Strip’的意思是飞机降落跑道,这是一个逗逼测试人员弄出来的,像一架飞机降落一样的视图。

  这个是坠机了的视图……

  LIST视图

  一个简单的列表视图

  PROGRESS视图

  包含一个简单的进度条的视图

  JSON视图

  输出一个JSON作为测试结果

  ##JSON STREAM视图

  输出的也是一个JSON,只不过输出的时候会带上换行

  JSONCOV覆盖率报告

  一个依赖 node-jscoverage 模块生成的视图,用来生成覆盖率报告

  HTMLCOV覆盖率报告

  用来生成一个覆盖率的html报告

  https://github.com/expressjs/express/commit/b6ee5fafd0d6c79cf7df5560cb324ebee4fe3a7f

  MIN视图

  只显示总体测试情况

  DOC视图

  生成一个只包含html的body部分的报告,结构如下:

  例如,测试代码如下:

  describe('Array', function() {

  describe('#indexOf()', function() {

  it('should return -1 when the value is not present', function() {

  [1,2,3].indexOf(5).should.equal(-1);

  [1,2,3].indexOf(0).should.equal(-1);

  });

  });

  });

  运行命令 mocha --reporter doc array ,结果:

  

  

Array

  

  

  

#indexOf()

  

  

  

  

should return -1 when the value is not present
[1,2,3].indexOf(5).should.equal(-1);
  

  [1,2,3].indexOf(0).should.equal(-1);

  

  

  

  自己添加head、html等标签,再加上style,可以生成自定义样式的报告。

  MARKDOWN视图

  生成一个markdown版本的报告,例子: https://github.com/senchalabs/connect/blob/90a725343c2945aaee637e799b1cd11e065b2bff/tests.md

  HTML视图

  目前只有在浏览器中运行的mocha才能直接生成html报告,nodejs中可以通过doc视图或者markdown视图得到的内容自己用脚本生成html版本的~

  第三方报告生成器

  mocha允许我们自己定义第三方的报告生成器,可以参考 文档 。

  一个例子: TeamCity reporter

  在浏览器中运行mocha

  mocha项目下都会有mocha.js和mocha.css供浏览器中的测试使用

  只能在浏览器中使用的函数

  mocha.allowUncaught() ,未捕获的错误不会被抛出

  下面是一个例子,在加载测试脚本之前,用 mocha.setup('bdd') 函数把测试模式设置为BDD接口,测试脚本加载完之后用 mocha.run() 函数来运行测试

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  GREP

  浏览器中可以通过在url后边加 ?grep=api 参数,来使用grep命令

  浏览器中的mocha配置

  可以通过 mocha.setup() 命令来设置配置

  // Use "tdd" interface. This is a shortcut to setting the interface;

  // any other options must be passed via an object.

  mocha.setup('tdd');

  // This is equivalent to the above.

  mocha.setup({

  ui: 'tdd'

  });

  // Use "tdd" interface, ignore leaks, and force all tests to be asynchronous

  mocha.setup({

  ui: 'tdd',

  ignoreLeaks: true,

  asyncOnly: true

  });

  浏览器中特有的选项

  noHighlighting

  如果被设置为true,mocha不会尝试用高亮语法输出测试代码

  MOCHA.OPTS(mocha配置)

  在服务端运行的时候,mocha会去加载test目录下的 mocha.opts 文件,来读取mocha配置项。这个配置文件中的每一行代表一项配置。如果运行mocha命令的时候,带上的配置参数与这个配置文件中的配置冲突的话,以命令中的为准。例如:

  –require should

  –reporter dot

  –ui bdd

  上面的配置就会让mocha 引入一下should模块、报告样式设置为dot,并且使用bdd的测试接口。

  test/ 目录

  默认情况下,mocha会去当前路径下的去找 ./test/*.js 或者 ./test/*.coffee 当做测试文件,所以测试文件应该放在test目录下

    bxmeng 还犹豫什么!快速的联系我们! 010-51297073