9

Mocha.js官方文档翻译 —— 简单、灵活、有趣

 3 years ago
source link: https://www.jianshu.com/p/9c78548caffa
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Mocha.js官方文档翻译 —— 简单、灵活、有趣

Mocha.js官方文档翻译 —— 简单、灵活、有趣

0.9932016.10.08 08:10:31字数 6,016阅读 16,351

本次翻译时间为2016年9月底,目前Mocha的版本为3.1.0。
官方文档地址: http://mochajs.org/
—— Awey

Mocha是一个能够运行在Node和浏览器中的多功能的JavaScript测试框架,它让异步测试简单且有趣。Mocha连续地运行测试,并给出灵活而精确的报告,同时能够将错误精确地映射到测试用例上。它托管在GitHub上。

2. 支持者

觉得Mocha很有帮助?成为支持者并以每月捐赠的形式支持Mocha。

3. 赞助商

公司正在使用Mocha?询问你的上司或者市场部看看他们是否捐赠过Mocha。(如果捐赠过)你们公司的LOGO会展示在npmjs.com和我们的github仓库

  • 支持浏览器
  • 支持简单异步,包括promise
  • 测试覆盖率报告
  • 支持字符串比较
  • 提供JavaScript API来运行测试
  • 为持续集成等需求提供适当的退出状态
  • non-ttys 自动检测和禁用颜色
  • 异步测试超时
  • ... ...(后略)

略。
本次翻译并未完全按照官方文档的文档结构进行。

6. 开始使用

6.1 安装

npm 全局安装:

npm install --global mocha

或者作为开发依赖安装在项目中:

npm install mocha --save-dev

安装Mocha v3.0.0或者更新的版本,你需要v1.4.0或者更新版本的npm。此外,运行Mocha的Node版本不能低于v0.10

Mocha也能通过Bower安装,还可通过cdnjs进行引用。

6.2 起步

npm install mocha
mkdir test
$EDITOR test/test.js # 或者使用你喜欢的编辑器打开

在编辑器中:

var assert = require('assert')
describe('Array', function () {
  describe('#indexOf()', function() {
    it('未找到值时应当返回-1', function () {
      assert.equal(-1, [1, 2, 3].indexOf(4))
    })
  })
})

回到命令行:

Array
  #indexOf()
    √ 未找到值时应当返回-1

1 passing (9ms)

6.3 断言

Mocha允许你使用你喜欢的断言库。在之后的例子中,我们使用了Node中内置的断言模块——但通常情况下,只要它能抛出异常就行[1]。这意味着你可以使用下列断言库:

6.4 异步代码

用Mocha测试异步代码简单的不要不要的!测试运行完了调用一下回调函数就行。只需要在it()中添加一个回调[2],Mocha就知道应该等到这个回调被调用时才结束这个测试用例的运行。

describe('User', function () {
  describe(#'save()', function () {
    it('应当正常保存', function () {
      var user = new User('Luna')
      user.save(function (err) {
        if (err) done(err)
        else done()
      })
    })
  })
})

简便起见,done()函数接受一个error参数,所以上面的代码可以这么写:

describe('User', function () {
  describe(#'save()', function () {
    it('应当正常保存', function () {
      var user = new User('Luna')
      user.save(done)
  })
})
Promise

有时,与其使用done()回调函数,你会想在你的异步代码中返回一个Promise[3],当你正在测试的API是返回一个Promise而不是使用回调时这会很有帮助:

beforeEach(function () {
  return db.clear()
    .then(function () {
      return db.save([tobi, loki, jane])
    })
})

describe('#find()', function () {
  it('返回匹配的记录', function () {
    return db.find({ type: 'User' }).should.eventually.have.length(3)
  })
})

接下来的例子将会使用chai-as-promised来获得流畅的promise断言

在Mocha 3.0及更新的版本中,同时返回一个Promise和调用done()会导致一个异常,下面的代码是错误的:

const assert = require('assert')

it('应该结束这个测试用例', function (done) {
  return new Promise(function (resolve) {
    assert.ok(true)
    resolve()
  })
    .then(done)
})

上面的测试会报错:Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.。在v3.0.0以下的版本,done()会被忽略(而不会报错)。

6.5 同步代码

当测试同步代码的时候,省略回调函数[4],Mocha就会自动执行下一条测试。

describe('Array', function () {
  describe('#indexOf()', function () {
    it('没有找到时应当返回-1', function () {
      [1, 2, 3].indexOf(5).should.equal(-1)
      [1, 2, 3].indexOf(0).should.equal(-1)
    })
  })
})

6.6 箭头函数

不建议在Mocha中使用箭头函数(“lambdas”)。由于(箭头函数特殊的)this绑定语法,箭头函数无法访问Mocha的上下文。例如,下面的代码会因为使用了箭头函数而执行失败:

describe('my suit', () => {
  it('my test', () => {
    // 应当设置1000毫秒延迟,而不是执行失败
    this.timeout(1000)
    assert.ok(true)
  })
})

<small>当然如果你不需要使用Mocha的上下文,使用lambdas就没有问题了。然而这样的做的结果是你的测试代码将难以重构</small>

6.7 钩子函数

Mocha默认使用“BDD”风格的接口,提供了before()after()beforeEach()afterEach()四个钩子函数。这些函数可以用来(在测试前)做预处理工作或在测试后清理工作。

describe('hooks', function () {
  before(function () {
    // 在这个作用域的所有测试用例运行之前运行
  })

  after(function () {
    // 在这个作用域的所有测试用例运行完之后运行
  })

  beforeEach(function () {
    // 在这个作用域的每一个测试用例运行之前运行
  })

  afterEach(function () {
    // 在这个作用域的每一个测试用例运行之后运行
  })

  // 测试用例
})

测试用例和测试的钩子可以混合排列。(相同的)钩子函数会按照它们的书写顺序运行;(整体的运行顺序是)所有的before()钩子运行一次,然后是beforeEach()钩子,测试用例,afterEach()钩子(循环运行),最后是after()钩子(运行一次)

钩子函数的描述参数

所有的钩子在调用时都可以提供一个可选的“描述信息”的参数,以便在你的测试中更精确地定位错误。如果给一个钩子函数传入一个命名函数,当未提供“描述信息”参数的时候,这个命名函数的名称将被作为描述信息。

beforeEach(function () {
  // beforeEach hook
})

beforeEach(function namedFun () {
  // beforeEach: namedFun
})

beforeEach('一些描述信息' ,function () {
  // beforEach: 一些描述信息
})

所有钩子(before()after()beforeEach()afterEach())既可以是同步的也可以是异步的,(这一点上)它们的行为与普通的测试用例非常相似[5]

describe('连接', function () {
  var db = new Connection,
    tobi = new User('tobi'),
    loki = new User('loki'),
    jane = newUser('jane')

  beforeEach(function (done) {
    db.clear(function (err) {
      if (err) return done(err)
      db.save([tobi, loki, jane], done)
    })
  })

  describe('#find()', function () {
    it('返回匹配的记录', function (done) {
      db.find({type: 'User'}, function (err, res) {
        if (err) return done(err)
        res.should.have.length(3)
      })
    })
  })
})

你可以在任意(测试)文件中添加“全局”级别的钩子函数,例如,在所有describe()作用域之外添加一个beforeEach(),它的回调函数会在所有的测试用例运行之前运行,无论(这个测试用例)处在哪个文件(这是因为Mocha有一个隐藏的describe()作用域,称为“根测试套件 root suite”)。

beforeEach(function () {
  console.log('在所有文件的所有测试用例之前运行')
})
延迟的根测试套件

如果你需要在所有测试套件运行之前进行一些异步操作,你可以延迟根测试套件。以--delay参数运行mocha[6],这会在全局注入一个特殊的回调函数run()

setTimeout(function () {
  // 一些设置
  
  describe('我的测试套件', function () {
    // ...
  })

  run()
}, 5000)

6.8 挂起测试(Pending Tests)

“Pending”——“有人最终会编写这些测试用例”——没有传入回调函数的测试用例[7]

describe('Array', function () {
  describe('#indexOf()', function () {
    // 挂起的测试用例
    it('未找到时应当返回-1')
  })
})

挂起的测试用例会在报告中出现“pending”状态。

6.9 独占测试

通过向测试套件或测试用例函数添加.only后缀,独占特性允许你只运行指定的测试套件或测试用例。下面是一个独占测试套件的例子:

describe('Array', function (){
  describe.only('#indexOf()', function () {
    // ...
  })
})

<small>注意:所有嵌套(在.only套件中的)测试套件仍旧会运行</small>
下面是一个运行单个测试用例的例子:

describe('Array', function (){
  describe('#indexOf()', function () {
    it.only('除非找到否则返回-1', function () {
      // ...
    })

    it('找到后应当返回下标', function () {
      // ...
    })
  })
})

在v3.0.0版本以前,only()使用字符串匹配来决定哪些测试需要执行。v3.0.0以后的版本only()可以使用多次来定义测试用例的子集去运行:

describe('Array', function() {
  describe('#indexOf()', function() {
    it.only('should return -1 unless present', function() {
      // 这个测试用例会运行
    })

    it.only('should return the index when present', function() {
      // 这个测试用例也会运行
    })
    
    it('should return -1 if called with a non-Array context', function() {
      // 这个测试用例不会运行
    })
  })
})

你也可以选择多个测试套件:

describe('Array', function() {
  describe.only('#indexOf()', function() {
    it('should return -1 unless present', function() {
      // 这个测试用例会运行
    })

    it('should return the index when present', function() {
      // 这个测试用例也会运行
    })
  })
  
  describe.only('#concat()', function () {
    it('should return a new Array', function () {
      // 这个测试用例也会运行
    })
  })
  
  describe('#slice()', function () {
    it('should return a new Array', function () {
      // 这个测试用例不会运行
    })
  })
})

但测试会存在优先级[8]

describe('Array', function() {
  describe.only('#indexOf()', function() {
    it.only('should return -1 unless present', function() {
      // 这个测试用例会运行
    })

    it('should return the index when present', function() {
      // 这个测试用例不会运行
    })
  })
})

<small>注意,如果提供了钩子函数,钩子函数仍会执行</small>

<small>注意不要把 .only 提交到版本控制上,除非你明确知道你在做什么</small>

6.10 跳过测试

这个功能是only()的反面。通过后缀skip()就可以让Mocha忽略这个测试套件或测试用例。所有被跳过的测试都会被标记为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() {
      // 这个测试用例会运行
    })
  })
})

最佳实践:使用skip()而不是直接将测试注释掉

你也可以使用this.skip()在运行时跳过测试。如果测试需要的环境或配置没办法提前检测,可以考虑使用运行时跳过。例如:

it('应该仅在正确的环境配置中测试', function () {
  if(/*测试环境正确*/) {
    // 编写断言
  } else {
    this.skip()
  }
})

因为这个测试什么也没做[9],它会被报告为passing

最佳实践:不要什么也不做[10]!一个测试应当编写断言或者使用this.skip()

如果想以这种方式跳过多个测试[11],可以在一个befor()钩子函数中调用this.skip()

before(function() {
  if (/* check test environment */) {
    // setup code
  } else {
    this.skip()
  }
})

在Mocha v3.0.0版本以前,钩子函数和异步测试中不支持this.skip()

6.11 重试测试

你可以选择将失败的测试重试一定的次数。这个特性被设计用于资源(数据)不容易被仿造的端到端(end-to-end)测试(functional tests/Selenium…)。不推荐将这个特性用于单元测试

这个特性会重新运行beforeEach()/afterEach()钩子,但不会运行before()/after()钩子。

注意:下面的例子使用了Selenium webdriver(为Promise链式调用改写了Mocha的全局钩子)。

describe('retries', function() {
  // 测试套件中的所有测试用例将被重试4次
  this.retries(4)
  
  beforeEach(function () {
    browser.get('http://www.yahoo.com');
  })
  
  it('should succeed on the 3rd try', function () {
    // 指定这个测试用例仅重试2次
    this.retries(2)
    expect($('.foo').isDisplayed()).to.eventually.be.true
  })
})

6.12 动态生成测试

可以使用Function.prototype.call和函数表达式来定义测试套件和测试用例,以动态生成测试而不需要其它的特殊语法——简单的JavaScript就能用于实现你可能在其它测试框架中见到过的类似“参数化”测试的功能。

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

上面的代码将会生成一个带有三个测试用例的测试套件:

$ mocha

  add()
    ✓ correctly adds 2 args
    ✓ correctly adds 3 args
    ✓ correctly adds 4 args

6.13 测试耗时

许多测试报告都会显示测试耗时,并且标记出那些耗时较长的测试,就像下面的报告显示的那样:

你可以使用slow()方法来定义到底多久才算“耗时较长”:

describe('something slow', function() {
  this.slow(10000)

  it('它的耗时应该足够我去做个三明治了', function() {
    // ...
  })
})

6.14 测试超时

套件级别的超时应用于整个测试套件,你也可以通过this.timeout(0)来取消超时限制。如果没有覆盖这个值的话[12],所有嵌套的测试套件和测试用例都会继承这个超时限制。

describe('a suite of tests', function() {
  this.timeout(500)

  it('应当不超过500毫秒', function(done){
    setTimeout(done, 300)
  })

  it('也应当不超过500毫秒', function(done){
    setTimeout(done, 250)
  })
})

也可以对单一用例设置超时时间,或者通过this.timeout(0)来取消超时限制:

it('应该不超过500毫秒', function(done){
  this.timeout(500)
  setTimeout(done, 300)
})

当然也可以设置钩子级别的超时:

describe('一个测试套件', function() {
  beforeEach(function(done) {
    this.timeout(3000); // 一个用时很长的环境设置操作.
    setTimeout(done, 2500)
  })
})

同样,使用this.timeout(0)来取消超时限制

在v3.0.0或更新的版本中,给this.timeout()传递一个大于最大延迟值的参数会让超时限制失效

6.15 差异比较

Mocha支持断言库抛出的AssertionErrors的两个属性err.expectederr.actual。Mocha会尝试显示期望(的代码)和断言库真正看到的的代码之间的差异。这里有一个“string”差异的例子:

“string”差异

7. 命令行

Usage: mocha [debug] [options] [files]


Commands:

  init <path>  initialize a client-side mocha setup at <path>

Options:

  -h, --help                              显示使用帮助
  -V, --version                           显示版本信息
  -A, --async-only                        强制所有测试带有回调(异步)或返回一个promise
  -c, --colors                            强制启用颜色
  -C, --no-colors                         强制关闭颜色
  -G, --growl                             启用弹出消息
  -O, --reporter-options <k=v,k2=v2,...>  测试报告工具详细设置
  -R, --reporter <name>                   指定测试报告工具
  -S, --sort                              测试文件排序
  -b, --bail                              第一次测试不通过立即结束测试
  -d, --debug                             开启node的debugger模式, 同node --debug
  -g, --grep <pattern>                    只运行匹配<pattern>的测试
  -f, --fgrep <string>                    只运行包含<string>的测试
  -gc, --expose-gc                        暴露gc扩展
  -i, --invert                            反转--grep 和--fgrep 匹配
  -r, --require <name>                    加载指定模块
  -s, --slow <ms>                         以毫秒为单位定义"慢" 测试门槛 [75]
  -t, --timeout <ms>                      以毫秒为单位设置测试用例超时时间 [2000]
  -u, --ui <name>                         指定用户接口 (bdd|tdd|qunit|exports)
  -w, --watch                             监测文件变动
  --check-leaks                           检查全局变量泄露
  --full-trace                            显示完整的跟踪堆栈
  --compilers <ext>:<module>,...          使用指定的模块编译文件
  --debug-brk                             在首行启用node的debugger断点
  --globals <names>                       allow the given comma-delimited global [names](没办法强行翻译了)
  --es_staging                            开启所有过时的特性
  --harmony<_classes,_generators,...>     all node --harmony* flags are available
  --preserve-symlinks                     命令模块加载器在解析和缓存模块时保留符号链接
  --icu-data-dir                          包括ICU数据
  --inline-diffs                          在行内显示实际/预期的字符差异
  --interfaces                            显示可用的接口(bdd|tdd|qunit|exports)
  --no-deprecation                        禁用警告
  --no-exit                               请求一个彻底的事件循环终止: Mocha不会调用 process.exit
  --no-timeouts                           禁用超时, 隐含 --debug
  --opts <path>                           指定选项路径
  --perf-basic-prof                       enable perf linux profiler (basic support)
  --prof                                  记录统计分析信息
  --log-timer-events                      记录包含外部回调的时间点
  --recursive                             包含子目录
  --reporters                             显示可用的测试报告工具
  --retries <times>                       设置重试未通过的测试用例的次数
  --throw-deprecation                     当使用了废弃的方法时抛出异常
  --trace                                 追踪函数借调
  --trace-deprecation                     显示废弃的跟踪堆栈
  --use_strict                            强制严格模式
  --watch-extensions <ext>,...            --watch 上附加的监控扩展
  --delay                                 等待异步套件定义

-w--watch

初始化后,监测文件变动运行测试

--compilers

CoffeeScript不再被直接支持。这类预编译语言可以使用相应的编译器扩展来使用,比如CS1.6:--compilers coffee:coffee-script 和CS1.7+:--compilers coffee:coffee-script/register

babel-register

如果你的ES6模块是以.js为扩展名的,你可以npm install --save-dev babel-register,然后--require babel-register; --compilers就可以指定文件扩展名

-b--ball

只对首个异常感兴趣?使用--bail

-d--debug

开启node的调试模式,这会用node debug <file ...>来执行你的脚本,允许你逐行调试代码并用debugger声明来打断点。注意mocha debugmocha --debug的区别:mocha debug会启动node内置的debug客户端,mocha --debug则允许你使用其它调试工具——比如Blink Developer Tools。

--globals <name>

接受一个以逗号分隔的全局变量名,例如,如果你的应用有意暴露一个全局变量名appYUI,你可能就会使用--globals app,YUI。它还接受通配符。--globals '*bar'会匹配foobar, barbar等。你也可以简单地传入*来忽略所有全局变量。

check-leaks

在运行测试时,Mocha默认不会检查全局变量泄露,可以使用--check-leaks来开启这一功能,使用--globals来指定接受的全局变量比如--globals jQuery,MyLib

-r--require <module-name>

--require选项对诸如should.js一类的库很有用,所以你可以使用--require should而不是在每一个测试文件中都调用require('should')。需要注意的是因为should是增强了Object.prototype所以可以正常使用,然而假如你希望访问某模块的输出你就只能require它们了,比如var should = require('should')。此外,还可以使用相对路径,比如--reqiure ./test/helper.js

-u--ui <name>

--ui选项让你指定想使用的接口,默认为“bdd”。

-R--reporter <name>

--reporter选项允许你指定希望使用的报告器,默认为“spec”。这个标记也可以用来使用第三方的报告器。例如,如果你npm install mocha-locv-reporter,你可以--reporter mocha-locv-reporter

-t--timeout <ms>

指定测试用例超时时间,默认为2秒。你可以传入毫秒数或者一个带s单位后缀的秒数进行覆盖,例如--timeout 2s--timeout 2000是等价的。

s--slow <ms>

指定“慢”测试阈值,默认为75毫秒。Mocha用这个去高亮那些耗时过长的测试。

-g--grep <pattern>

指定--grep选项让Mocha只运行匹配<pattern>的测试,<pattern>将会作为正则表达式进行解析。

假如,像下面的片段那样,你有一些“api”相关的测试和一些“app”相关的测试;则前者可以使用--grep api来运行,后者可使用--grep --app来运行

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() {
      // ...
    })
  })
})

8.接口[13]

Mocha的“接口”系统允许开发者选择习惯的风格或DSL。Mocha有BDDTDDExportsQUnitRequire风格的接口。

8.1 BDD

BDD接口提供describe()context()it()specify()before()after()beforeEach()afterEach()

context()只是describe()的别名,二者表现也是一致的;它只是为了让测试可读性更高。同样specify()也是it()的别名。

前文所有的示例都是使用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)
      })
    })
  })
})

8.2 TDD

TDD接口提供suite()test()suiteSetup()suiteTeardown()setupteardown()

suite('Array', function() {
  setup(function() {
    // ...
  })

  suite('#indexOf()', function() {
    test('should return -1 when not present', function() {
      assert.equal(-1, [1,2,3].indexOf(4));
    })
  })
})

8.3 EXPORTS

EXPORTS接口很像Mocha的前身expresso,键值beforeafterbeforeEachafterEach是特殊用例,对象类型的属性值是测试套件,方法类型的属性值是测试用例:

module.exports = {
  before: function() {
    // ...
  },

  'Array': {
    '#indexOf()': {
      'should return -1 when not present': function() {
        [1,2,3].indexOf(4).should.equal(-1)
      }
    }
  }
}

8.4 QUNIT

QUnit接口与QUnit的“扁平化”外观相匹配[14],测试套件只需要简单地在测试用例之前定义就行。和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)
})

8.5 REQUIRE

require风格接口允许你直接用require语句引入describe等函数并在任意位置使用它们。当你希望在你的测试中禁用全局变量时这也会很有用。

<small>注意,require风格接口不能通过node直接运行,必须通过Mocha运行</small>

var 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)
    })
  })
})

9. 测试报告

Mocha的测试报告与命令行窗口适配,且当标准输出串口没有关联到打印机时始终禁用ANSI-escape颜色。

9.1 SPEC

这是默认的测试报告。“SPEC”测试报告输出与测试用例一致的嵌套视图。

spec 测试报告
带有失败状态的spec 测试报告

9.2 Dot Matrix

Dot Matrix(或者Dot)测试报告使用一串简单字符来表示测试用例,失败的(failing)以红色叹号(!)表示,挂起的(pedding)以蓝色逗号(,)表示,长时的以黄色表示。当你希望最小化输出的时候这就很好。

dot matrix 测试报告

9.3 NYAN

NYAN测试报告就是你想的那样(一只猫):

js nyan cat 测试报告

9.4 TAP

TAP测试报告的输出很适合Test-Anything-Protocol的用户。

test anything protocol

9.5 Landing Strip

landing Strip(landing)测试报告是一个非正式的测试报告器,它用unicode字符模仿了飞机降落的情景。

landing strip plane 测试报告
带失败状态的landing strip测试报告

9.6 LIST

list测试报告输出一个测试用例通过或失败的简洁列表,并在底部输出失败用例的详情。

list测试报告

9.7 PROGRESS

progress测试报告展示一个简单进度条。

progress bar

9.8 JSON

JSON测试报告在测试完成后输出一个大JSON对象。

json reporter

9.9 JSON STREAM

JSON stream测试报告输出根据“事件”断行了的JSON,以“start”事件开始,紧跟着测试通过或失败,最后是“end”事件。

json stream reporter

9.10 MIN

min测试报告仅显示结果摘要,当然也输出失败时的错误信息。当与--watch一起使用时很棒,它会清空你的命令行让测试摘要始终显示在最上方。

min reporter

9.11 DOC

doc测试报告输出一个层级化的HTML来表示你的测试结果。使用header,footer和一些样式来包裹测试结果,然后你就有了一份惊艳的测试报告文档!

doc reporter

例如,假定你有下面的JavaScript:

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会输出:

<section class="suite">
  <h1>Array</h1>
  <dl>
    <section class="suite">
      <h1>#indexOf()</h1>
      <dl>
      <dt>should return -1 when the value is not present</dt>
      <dd><pre><code>[1,2,3].indexOf(5).should.equal(-1);
[1,2,3].indexOf(0).should.equal(-1);</code></pre></dd>
      </dl>
    </section>
  </dl>
</section>

The SuperAgent request library test documentation was generated with Mocha’s doc reporter using this simple make target:

test-docs:
    $(MAKE) test REPORTER=doc \
        | cat docs/head.html - docs/tail.html \
        > docs/test.html

View the entire Makefile for reference.

9.12 MARKDOWN

markdown测试报告为你的测试讨价能生成一个markdown TOC。当你希望将你的测试结果放在Github的wiki或仓库中时,这会很好用。这是一个例子的链接测试输出

9.13 HTML

HTML测试报告是当前Mocha唯一支持的浏览器测试报告,长得像这样:

HTML test reporter

9.14 未记载的测试报告

XUnit测试报告也是可以用的。默认地,它输出到console。想直接写入文件,使用--reporter-options output=filename.xml

9.15 第三方的测试报告

Mocha允许自定义第三方的测试报告生成器。浏览wiki获取更多信息。一个例子是TeamCity reporter

10. 在浏览器中运行Mocha

Mocha可以运行在浏览器中。Mocha的每个释出版本都会有./mocha.js./mocha.css来在浏览器中使用。

10.1 浏览器专用方法

下面的方法仅在浏览器环境中有效:
mocha.allowUncaught():如果调用,未捕获的错误不会被error handler处理。

一个典型的设置看起来可能像下面这样,在载入测试脚本,在onload中用mocha.run()运行它们之前,我们调用mocha.setup('bdd')来使用BDD风格的接口。

<html>
<head>
  <meta charset="utf-8">
  <title>Mocha Tests</title>
  <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" />
</head>
<body>
  <div id="mocha"></div>

  <script src="https://cdn.rawgit.com/jquery/jquery/2.1.4/dist/jquery.min.js"></script>
  <script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script>
  <script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>

  <script>mocha.setup('bdd')</script>
  <script src="test.array.js"></script>
  <script src="test.object.js"></script>
  <script src="test.xhr.js"></script>
  <script>
    mocha.checkLeaks();
    mocha.globals(['jQuery']);
    mocha.run();
  </script>
</body>
</html>

10.2 grep

浏览器中也可以使用--grep功能。在你的URL上添加一个请求参数:?grep=api

10.3 浏览器配置

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

10.4 浏览器专用选项

下面的选项仅在浏览器环境有效:
noHighlighting:如果设置为true,do not attempt to use syntax highlighting on output test code。

mocha.opts

回到服务器,Mocha会试图加载./test/mocha.opts作为Mocha的配置文件。文件是由命令行参数按行拼接起来的。命令行参数也是有优先级的,例如,假定你有下面的mocha.opt文件:

--require should
--reporter dot
--ui bdd

它会将默认测试报告设置为dot,加载should断言库,并使用BDD风格的接口。然后你可能会继续带参数运行Mocha,这里是开启Growl支持,并将测试报告更换为list:

$ mocha --reporter list --growl

11. test/文件夹

Mocha默认会全局寻找./test/*.js./test/*.coffee,所以你可能需要将你的测试文件放到./test文件夹中

12. 编辑器插件

下面的编辑器插件package可用:

12.1 TextMate

Mocha的TextMate包包含了能够加速测试编写的代码片段。克隆Mocha repo并运行make tm来安装这个包

12.2 JetBrains

JetBrains为它们的IDE套件(IntelliJ IDEA,WebStorm等)提供了一个NodeJS插件,包含了一个Mocha test runner,和一些周边。

运行中的JetBrains Mocha Runner Plugin

插件名为NodeJS,并且可以通过Preference > Plugins来安装...如果你的许可允许的话。

12.3 Wallaby.js

Wallaby.js是一个持续测试工具,为JetBrains IDE和Visual Studio中的Mocha提供实时的测试覆盖率,不管是运行在node.js还是浏览器的项目。

运行中的Wallaby.js

12.4 Emacs

Emacs支持通过第三方插件mocha.el来运行Mocha测试。插件可以在MELPA上找到,也可通过M-x package-install mocha来安装。

运行中的Emacs Mocha Runner

13. 案例

真实案例代码:

14. 测试Mocha

运行Mocha本身的测试,你可能需要GUN Make或者其它兼容的环境;Cygwin应该就可以。

$ cd /path/to/mocha
$ npm install
$ npm test

使用不同的测试报告:

$ REPORTER=nyan npm test

15. 更多信息

除了在Gitter上与我们交谈,也可以去GitHub上的Mocha Wiki获取诸如 using spies、mocking和shared behaviours等更多信息。加入Google Group进行讨论。查看example/tests.html获取Mocha运行实例。查看source获取 JavaScript API。


  1. 译者注:这里的意思是,只要这个断言库在遇到测试不通过时会抛出异常(throws an Error),它就可以使用在Mocha中。这意味着即使你不使用任何断言库,完全自己实现测试代码,只要在遇到测试部不通过时你抛出异常,也是可以的,不过通常没有人愿意这么费力不讨好

  2. 译者注:在it()函数的第二个参数,也就是it的回调函数中,添加一个参数,这个参数也是一个回调函数,命名随意,通常都会命名为done,然后在异步代码运行完毕后调用它即可

  3. 译者注:这是为了避开无穷的回调漩涡

  4. 译者注:这里指的是省略done()这个回调函数

  5. 译者注:还记得前文提到的done()回调函数么,在这些钩子中处理异步代码与在测试用例中处理异步代码是一样的

  6. 译者注:这是指在命令行运行 mocha 命令时带上 --delay参数,下文的setTimeout仅做演示用,并非真实的异步操作

  7. 译者注:这里的意思是,可以使用挂起的测试用例来占个位置,先写上测试用例,但可能由于某些原因,比如被测代码还未实现,这个测试用例的内容将在稍后编写,这样的测试用例既不会pass也不会fail,而是处于pendding状态

  8. 译者注:这里指的是嵌套的only()会存在优先级

  9. 译者注:这里所谓的“什么也没做”指的是当测试环境不正确时,测试代码什么也没做,只是简单的跳过了

  10. 译者注:这里的“什么也不做”与前文的“什么也不做”不是一个意思,这里的意思是既不写断言也不跳过,只是简单地空在那里(简单地空在那里这个测试的状态也会是passing)

  11. 译者注:这种方式指的是,判断测试环境是否准本好并使用this.skip()来跳过测试

  12. 译者注:“覆盖这个值”指的是在嵌套的测试套件或者测试用例中再次通过this.timeout()来进行超时限制从而覆盖父级套件的设置

  13. 译者注:指的是接口风格

  14. 译者注:这里指的是编程风格扁平化,即没有多层嵌套

34人点赞
更多精彩内容,就在简书APP
"小礼物走一走,来简书关注我"
共1人赞赏
Awey我搬到知乎了:<a href="https://links.jianshu.com/go?to...
总资产152共写了6.5W字获得520个赞共326个粉丝

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK