使用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格式的報告





參照連接:

相關文章
相關標籤/搜索