使用mocha测试

 

学习了MOCHA官网的示例,将学习成果记录一下。【原文+例子:使用mocha测试javascript

 

mocha是什么

Mocha是一个跑在node和浏览器上的javascript测试框架,让异步测试变得简单有趣, 并提供灵活精确的报告。java

安装

使用npm全局安装node

$ npm install --global mocha $ npm install --global mocha

做为项目开发依赖安装linux

$ npm install --save-dev mocha $ npm install --save-dev mocha

开始

建立测试文件learn-mochagit

$ npm install mocha -g // 全局安装mocha $ mkdir test // 建立test文件夹 $ touch test.js // 建立test文件 $ npm install mocha -g // 全局安装mocha $ mkdir test // 建立test文件夹 $ touch test.js // 建立test文件

例子

var assert = require('assert'); describe('Array', function() { describe('#indexOf()', function() { it('should return -1 when the value is not present', function() { assert.equal([1,2,3].indexOf(4), -1); }); }); }); 

例子中使用了测试集定义函数describe()和测试用例定义函数it(),先引入nodeassert模块的eaual()方法用来验证两数是否相等:[1,2,3].indexOf(4) == -1github

learn-mocha git:(master) ✗ mocha Array #indexOf() ✓ should return -1 when the value is not present 1 passing (7ms) learn-mocha git:(master) ✗ mocha Array #indexOf() ✓ should return -1 when the value is not present 1 passing (7ms)

在终端输入mocha,能够看到测试用例经过了。chrome

Mocha的执行会找到当前命令执行目录下的test目录。./test/*.jsMocha寻找的目标。 也能够在package.json中设置以下设置,就可使用npm test命令行开启Mocha测试数据库

"scripts": { "test": "mocha" } 

断言ASSERTIONS

Mocha支持各类断言库来验证功能,例如should.js、chai、expect.js、better-assert、unexpected等express

异步模式

在mocha中测试异步代码并不容易。经过给it()加一个回调函数(一般命名为done),mocha将会知道异步代码执行以后须要调用done来表示测试完成。npm

describe('User', function() { describe('#save()', function() { it('should save without error', function(done) { var user = new User('Luna'); user.save(function(err) { if (err) done(err); else done(); }); }); }); }); 

当done()能够接受异步代码错误的时候,上面代码还能够简化为

describe('User', function() { describe('#save()', function() { it('should save without error', function(done) { var user = new User('Luna'); user.save(done); }); }); }); 

使用PROMISES

除了使用回调函数done(), 你还能够返回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); }); }); 

使用async/await

若是js环境支持 async/await, 你能够这样写异步测试

beforeEach(async function() { await db.clear(); await db.save([tobi, loki, jane]); }); describe('#find()', function() { it('responds with matching records', async function() { const users = await db.find({ type: 'User' }); users.should.have.length(3); }); }); 

同步模式

当测试同步代码时,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中使用箭头函数,由于箭头函数对this的绑定会使测试用例没法访问Mocha上下文中的一些方法。

describe('my suite', () => { it('my test with arrow function', () => { // should set the timeout of this test to 1000 ms; instead will fail this.timeout(1000); assert.ok(true); }); }); describe('my suite', function () { it('my test without arrow function', function() { // set the timeout of this test to 1000 ms; passing this.timeout(1000); assert.ok(true); }); }); 

HOOKS

Mocha提供了四种hooks用来作测试准备和测后清理工做

  • before() 在全部测试套件运行以前运行
  • after() 在全部测试套件运行以后运行
  • beforeEach() 在每一个测试用例运行以前运行
  • afterEach() 在每一个测试用例运行以后运行
var assert = require('assert'); describe('hooks', function() { before(function() { console.log('runs before all tests in this block') }); after(function() { console.log('runs after all tests in this block') }); beforeEach(function() { console.log('runs before each test in this block') }); afterEach(function() { console.log('runs after each test in this block') }); it('test 1', function(){ assert.ok(true) }) it('test 2', function(){ assert.ok(true) }) }); 
➜  learn-mocha git:(master) ✗ mocha test/hooks.js

  hooks
runs before all tests in this block runs before each test in this block ✓ test 1 runs after each test in this block runs before each test in this block ✓ test 2 runs after each test in this block runs after all tests in this block 2 passing (8ms) 

描述HOOKS

任何钩子在回调前都有一个可选的描述,在测试中能更简单定位到错误。若是一个钩子是命名函数,在没有描述时,将会使用函数名。

beforeEach(function() { // beforeEach hook }); beforeEach(function namedFun() { // beforeEach:namedFun }); beforeEach('some description', function() { // beforeEach:some description }); 

异步HOOKS

全部hooks(before(), after(), beforeEach(), afterEach()) 都有多是同步或者异步,就像一个常规的测试。例如,您可能但愿在每一个测试以前填充虚拟内容的数据库:

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

延迟根suite

若是你须要在全部suites运行以前执行异步操做,你可能会延迟根suite。用--delay运行mocha。这将把一个特殊的回调函数,run()附加到全局上下文中:

setTimeout(function() { // do some setup describe('my suite', function() { // ... }); run(); }, 5000); 

待定测试(PENDING TESTS)

待定测试将包括在测试结果中,而且标记为pending。未决测试不被认为是失败的测试。不添加回调函数callback便可。

describe('#indexOf()', function() { // pending test below it('should return -1 when the value is not present'); }); }); 
learn-mocha git:(master) ✗ mocha test/pending.js

  Array #indexOf() - should return -1 when the value is not present 0 passing (5ms) 1 pending 

it()中没有回调函数,就会显示 0 passing 1 pending

独有测试(EXCLUSIVE TESTS)

能够经过添加.only()describe()it()函数中,来指定测试套件。测试套件和测试用例能够屡次定义。若是在测试套件和测试用例同时都加上了.only()的时候,测试用例的执行是优先的。例如suite 2中,只执行了test case 5

const assert = require('assert') describe('suite 1', function () { describe('sub suite 1', function () { it('test case 1', function () { assert(true) }) it('test case 2', function () { assert(true) }) }) describe.only('sub suite 2', function () { it('test case 3', function () { assert(true) }) }) }) describe.only('suite 2', function () { it('test case 4', function () { assert(true) }) it.only('test case 5', function () { assert(true) }) }) 
➜  learn-mocha git:(master) ✗ mocha test/exclusive.js

  suite 1 sub suite 2 ✓ test case 3 suite 2 ✓ test case 5 2 passing (7ms) (5ms) 

跳过测试(INCLUSIVE TESTS)

与 .only() 相反,经过给describe()it()加上.skip(), mocha 会忽略这些测试套件或者测试用例。这些被跳过的测试都会被标记为pending

const assert = require('assert') describe('suite 1', function () { describe('sub suite 1', function () { it('test case 1', function () { assert(true) }) it('test case 2', function () { assert(true) }) }) describe.skip('sub suite 2', function () { it('test case 3', function () { assert(true) }) }) }) describe.skip('suite 2', function () { it('test case 4', function () { assert(true) }) it.skip('test case 5', function () { assert(true) }) }) let checkTestEnviroment = false describe('suite 3', function () { it('test case 6', function () { if (checkTestEnviroment) { assert(true) } else { this.skip() } }) it('test case 7', function () { assert(true) }) }) 

从执行结果来看,test case 3 和 suite 2 和 test case 6 套件都进入了 pending 待定状态。 test case 3 是由于测试用例 it.skip 。 suite 2 是由于测试套件 describe.skip 。 test case 6 是由于使用了 this.skip() ,模拟环境 checkTestEnviroment 有问题,须要跳过测试,最后跳过的测试会被标记为 pending 。

➜  learn-mocha git:(master) ✗ mocha test/inclusive.js

  suite 1 sub suite 1 ✓ test case 1 ✓ test case 2 sub suite 2 - test case 3 suite 2 - test case 4 - test case 5 suite 3 - test case 6 ✓ test case 7 3 passing (9ms) 4 pending 

使用 .skip() 是比注释更好的可以不执行指定测试的方法。

重跑测试(RETRY TESTS)

能够选择 this.retries(number) 来从新执行失败的测试到必定的次数。这个函数是为了处理资源不容易被模拟和截断的 end-to-end 测试而设计的,因此不推荐在单元测试里使用。

this.retries(number) 做用在 beforeEach/afterEach hooks中,可是不做用在 before/after hooks中。

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

动态生成测试(DYNAMICALLY GENERATING TESTS)

mocha 使用 Function.prototype.call 和函数表达式来定义测试套件和测试用例,这样能简单动态的生成测试用例。不须要特别的语法,只需 javascirpt 就能实现相似参数化测试的功能。

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); }); }); }); 
➜  learn-mocha git:(master) ✗ mocha test/dynamically-generate.js

  add()
    ✓ correctly adds 2 args ✓ correctly adds 3 args ✓ correctly adds 4 args 3 passing (11ms) 

测试持续时间(TEST DURATION)

在许多测试报告里会显示测试时间,当测试时间过长,会被特殊标记出来。可使用 slow() 方法,来定义被认为 slow 的测试时间长度。

describe('something slow', function() { this.slow(10000); it('should take long enough for me to go make a sandwich', function() { // ... }); }); 

测试超时(TIMEOUTS)

套件级别(SUITE-LEVEL)

在套件级别describe()定义this.timeout(numer),将会被运用于该套件下的全部嵌套套件和测试用例。

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

上面的代码定义了超时时间是500ms,而后测试执行时间都没有超过,因此测试能够经过

➜  learn-mocha git:(master) ✗ mocha test/timeouts/suite-level.js

  a suite of tests ✓ should take less than 500ms (306ms) ✓ should take less than 500ms as well (251ms) 2 passing (564ms) 

若是把时间从this.timeout(500)改为this.timeout(300),,就会的到超时错误

➜  learn-mocha git:(master) ✗ mocha test/timeouts/suite-level.js

  a suite of tests 1) should take less than 300ms ✓ should take less than300ms as well (253ms) 1 passing (569ms) 1 failing 1) a suite of tests should take less than 300ms: Error: Timeout of 300ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/blog/learn-mocha/test/timeouts/suite-level.js) 

用例级别

在测试级别it()中使用方法也差很少。在it()中使用this.timeout(0)能够重载/消除测试套件定义的超时时间。

it('should take less than 500ms', function(done){ this.timeout(500); setTimeout(done, 300); }); 
➜  learn-mocha git:(master) ✗ mocha test/timeouts/test-level.js

  ✓ should take less than 500ms (302ms) 1 passing (308ms) 

钩子级别(HOOK-LEVEL)

在钩子级别HOOK-LEVEL中使用方法也差很少。使用this.timeout(0)也能够s禁用hook的超时。

describe('a suite of tests', function() { beforeEach(function(done) { this.timeout(3000); // A very long environment setup. setTimeout(done, 2500); }); it('it', function(done) { setTimeout(done, 20); }) }); 
➜  learn-mocha git:(master) ✗ mocha test/timeouts/hook-level.js

  a suite of tests ✓ it 1 passing (3s) 

DIFFS

mocha支持来自断言库的有err.expected 和 err.actual 实际属性的任何AssertionErrors错误 。mocha将自动显示预期和实际之间的差别。下面是一个“字符串”差别的例子:

const assert = require('assert') describe('suite 1', function () { it('test case 1', function () { assert.equal(-1, [1, 2, 3].indexOf(4)) }) it('test case 2', function () { assert.equal('test', [1, 2, 3].toString()) }) }) 
➜  learn-mocha git:(master) ✗ mocha test/diffs.js

  suite 1 ✓ test case 1 1) test case 2 1 passing (9ms) 1 failing 1) suite 1 test case 2: AssertionError [ERR_ASSERTION]: 'test' == '1,2,3' + expected - actual -test +1,2,3 at Context.<anonymous> (test/diffs.js:9:12) 

使用命令(USAGE)

➜ learn-mocha git:(master) ✗ mocha --help Usage: mocha [debug] [options] [files] Options: -V, --version output the version number -A, --async-only force all tests to take a callback (async) or return a promise -c, --colors force enabling of colors -C, --no-colors force disabling of colors -G, --growl enable growl notification support -O, --reporter-options <k=v,k2=v2,...> reporter-specific options -R, --reporter <name> specify the reporter to use (default: spec) -S, --sort sort test files -b, --bail bail after first test failure -d, --debug enable node's debugger, synonym for node --debug -g, --grep <pattern> only run tests matching <pattern> -f, --fgrep <string> only run tests containing <string> -gc, --expose-gc expose gc extension -i, --invert inverts --grep and --fgrep matches -r, --require <name> require the given module -s, --slow <ms> "slow" test threshold in milliseconds [75] -t, --timeout <ms> set test-case timeout in milliseconds [2000] -u, --ui <name> specify user-interface (bdd|tdd|qunit|exports) (default: bdd) -w, --watch watch files for changes --check-leaks check for global variable leaks --full-trace display the full stack trace --compilers <ext>:<module>,... use the given module(s) to compile files (default: ) --debug-brk enable node's debugger breaking on the first line --globals <names> allow the given comma-delimited global [names] (default: ) --es_staging enable all staged features --harmony<_classes,_generators,...> all node --harmony* flags are available --preserve-symlinks Instructs the module loader to preserve symbolic links whenresolving and caching modules --icu-data-dir include ICU data --inline-diffs display actual/expected differences inline within each string --no-diff do not show a diff on failure --inspect activate devtools in chrome --inspect-brk activate devtools in chrome and break on the first line --interfaces display available interfaces --no-deprecation silence deprecation warnings --exit force shutdown of the event loop after test run: mocha willcall process.exit --no-timeouts disables timeouts, given implicitly with --debug --no-warnings silence all node process warnings --opts <path> specify opts path (default: test/mocha.opts) --perf-basic-prof enable perf linux profiler (basic support) --napi-modules enable experimental NAPI modules --prof log statistical profiling information --log-timer-events Time events including external callbacks --recursive include sub directories --reporters display available reporters --retries <times> set numbers of time to retry a failed test case --throw-deprecation throw an exception anytime a deprecated function is used --trace trace function calls --trace-deprecation show stack traces on deprecations --trace-warnings show stack traces on node process warnings --use_strict enforce strict mode --watch-extensions <ext>,... additional extensions to monitor with --watch (default: js) --delay wait for async suite definition --allow-uncaught enable uncaught errors to propagate --forbid-only causes test marked with only to fail the suite --forbid-pending causes pending tests and test marked with skip to fail the suite --file <file> include a file to be ran during the suite (default: ) --exclude <file> a file or glob pattern to ignore (default: ) -h, --help output usage information Commands: init <path> initialize a client-side mocha setup at <path> ➜ learn-mocha git:(master) ✗ mocha --help Usage: mocha [debug] [options] [files] Options: -V, --version output the version number -A, --async-only force all tests to take a callback (async) or return a promise -c, --colors force enabling of colors -C, --no-colors force disabling of colors -G, --growl enable growl notification support -O, --reporter-options <k=v,k2=v2,...> reporter-specific options -R, --reporter <name> specify the reporter to use (default: spec) -S, --sort sort test files -b, --bail bail after first test failure -d, --debug enable node's debugger, synonym for node --debug -g, --grep <pattern> only run tests matching <pattern> -f, --fgrep <string> only run tests containing <string> -gc, --expose-gc expose gc extension -i, --invert inverts --grep and --fgrep matches -r, --require <name> require the given module -s, --slow <ms> "slow" test threshold in milliseconds [75] -t, --timeout <ms> set test-case timeout in milliseconds [2000] -u, --ui <name> specify user-interface (bdd|tdd|qunit|exports) (default: bdd) -w, --watch watch files for changes --check-leaks check for global variable leaks --full-trace display the full stack trace --compilers <ext>:<module>,... use the given module(s) to compile files (default: ) --debug-brk enable node's debugger breaking on the first line --globals <names> allow the given comma-delimited global [names] (default: ) --es_staging enable all staged features --harmony<_classes,_generators,...> all node --harmony* flags are available --preserve-symlinks Instructs the module loader to preserve symbolic links whenresolving and caching modules --icu-data-dir include ICU data --inline-diffs display actual/expected differences inline within each string --no-diff do not show a diff on failure --inspect activate devtools in chrome --inspect-brk activate devtools in chrome and break on the first line --interfaces display available interfaces --no-deprecation silence deprecation warnings --exit force shutdown of the event loop after test run: mocha willcall process.exit --no-timeouts disables timeouts, given implicitly with --debug --no-warnings silence all node process warnings --opts <path> specify opts path (default: test/mocha.opts) --perf-basic-prof enable perf linux profiler (basic support) --napi-modules enable experimental NAPI modules --prof log statistical profiling information --log-timer-events Time events including external callbacks --recursive include sub directories --reporters display available reporters --retries <times> set numbers of time to retry a failed test case --throw-deprecation throw an exception anytime a deprecated function is used --trace trace function calls --trace-deprecation show stack traces on deprecations --trace-warnings show stack traces on node process warnings --use_strict enforce strict mode --watch-extensions <ext>,... additional extensions to monitor with --watch (default: js) --delay wait for async suite definition --allow-uncaught enable uncaught errors to propagate --forbid-only causes test marked with only to fail the suite --forbid-pending causes pending tests and test marked with skip to fail the suite --file <file> include a file to be ran during the suite (default: ) --exclude <file> a file or glob pattern to ignore (default: ) -h, --help output usage information Commands: init <path> initialize a client-side mocha setup at <path>

解释几个经常使用的选项

  • -V, --version 版本号
  • -b, --bail 只对第一个抛出异常处理
  • -d, --debug 开启node的debug模式,对标记了debugger语句的代码进行调试
  • -t, --timeout <ms>指定测试用例的超时时间。默认是2000毫秒。
  • -w, --watch 用来监测测试文件的变化
  • -s, --slow <ms> 指定测试用例执行时间为慢的阈值。默认是75毫秒。

接口(INTERFACES)

mocha 的接口系统容许开发人员选择本身的DSL风格。mocha 拥有 BDDTDDExportsQUnit 和 Require风格的接口。

BDD

BDD 接口 提供 describe()context()it()specify()before()after()beforeEach()afterEach()。 describe() = context()it() = specify() 前面的例子都是用的 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

提供 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

相似于 mocha 前身 expresso。关键字 beforeafterbeforeEachafterEach 是special-cased。 测试套件是对象,函数是测试用例。

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

QUNIT

相似QUnit。测试套件单独定义在测试用例以前,像TDD同样支持suite()和test(),像BDD同样支持hooks。一样包括before()after()beforeEach()afterEach()

unction 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()来导入describe()it()的方法。能够本身定义别名。注意:只能用mocha命令执行,node不行。

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

报告(REPORTERS)

Mocha提供了多种console端报告模式

  • mocha --reporter spec 这是默认模式。是一个按照测试套件和用例分层次的视图
  • mocha --reporter dot 显示一个由点组成的矩阵。点的颜色表明着不一样的测试结果
  • mocha --reporter nyan 显示了一个图。。。。。
  • mocha --reporter tap 基于Test Anything Protocol (TAP)
  • mocha --reporter landing 模拟飞机降落
  • mocha --reporter list 以列表的形式显示每个测试用例
  • mocha --reporter progress 以进度条的形式显示
  • mocha --reporter json 输出json格式的报告
  • mocha --reporter min 只输出summary。能够与mocha -w一块儿使用
  • mocha --reporter doc 输出HTML格式的报告
  • mocha --reporter markdown 输出HTML格式的报告





参照连接:

相关文章
相关标签/搜索