這篇文章百分之99都是照着mocha官網的內容來寫的。就是個掃盲文,如果你想獲得關於mocha更深層次不為人知的內容,還是別浪費你寶貴的十幾分鍾了,馬上叉掉。不為啥的,我就做個筆記,方便以後複習。
mocha(抹茶)是一款javascript測試框架,支持在node和瀏覽器端運行。它比QUnit更完善,可擴展性更強。在官網上,對它的描述就是簡單,可擴展,有趣。(有趣是什麼鬼)
使用
// 1
npm install mocha -g
mocha ./test.js
// 2
npm install mocha --save-dev
node .node_modules/mocha/bin/mocha ./test.js
主要api
mocha只有兩個主要的api。
- describe(name, fn) 定義一組測試
- it(name, fn) 定義一項測試
describe('proxy', function(){
it('proxy data 1', function(done){
this.timeout(1000)
assert.ok(true, 'fail')
})
你也可以在一組測試裏面再定義一組測試
describe('group1', function(){
describe('child1', function(){
})
})
只測試其中某一組測試
describe('test', function(){
describe.only('testc1', function(){
})
})
跳過某一組測試
describe('test', function(){
describe.skip('testc1', function(){
})
})
斷言
mocha沒有佩戴自己的斷言庫,它允許你使用第三方斷言庫,如node 內置的assert, chai等。只要程序拋出一個錯誤,mocha就會認為測試不通過。
const assert = require('assert') // 使用node內置的斷言庫
describe('proxy', function(){
it('proxy data 1', function(done){
this.timeout(1000)
assert.ok(true, 'fail')
})
node assert 斷言
- assert.fail(String | Error)
拋出一個AssertionError, 如果參數是一個Error,則會拋出這個Error。 - assert.ifError(any)
只要any 不等於undefined | null 就拋出any - assert.ok(value[,maessage])
測試value 是否為真值 - assert.equal(actual, expected [,message]) | assert.notEqual(actual, expected [,message])
對actual 和 expected 執行 == 比較 - assert.strictEqual(actual, expected [,message]) | assert.notStrictEqual(actual, expected [,message])
對actual 和 expected 執行 === 比較 - assert.deepStrictEqual(actual, expected[,message]) | assert.notDeepStrictEqual()
測試是否深度全等, 執行的是=== 比較
異步測試
- 回調形式
describe('Array', function(){
it('should correct', function(done){
setTimeout(done,1000)
})
})
如果done()執行的時候有參數,如done('錯誤'), 那麼mocha判定測試不通過。 你也可以直接傳入一個Error對象到done函數中,如done(new Error('fail'))
- promise的形式
describe('Array', function(){
it('should correct', function(){
return Promise.resolve()
})
})
如果it 函數的返回值是一個promise, 將被是為是一個異步測試。並且根據promise的fullfill狀態來決定測試是否通過。
值得注意的是,當你覺得使用promise的形式時候,你就不應該再it的回調函數聲明參數done。這個會讓mocha認為你其實是想通過done的形式來完成異步測試的。
describe('Array', function(done){ // 這個done是不需要的。
it('should correct', function(){
return Promise.resolve()
})
})
- 使用async-await
describe('Array', async function(done){ // 這個done是不需要的。
it('should correct', function(){
let result = someAsyncOperation()
assert.ok(true, result)
})
})
箭頭函數
mocha不提倡使用箭頭函數,因為it, describe都是綁定mocha context執行的,在箭頭函數中,無法獲取到mocha context。如以下會報錯
describe('Array', () => {
it('shoule correct', (done) => {
this.timeout(1000) // can not read property timeout of undefind
})
})
hook
mocha 在整個測試周期中,提供了一組hook鈎子來讓開發者在測試開始之前準備環境或者是測試完成之後清理環境。
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
});
異步鈎子
在鈎子函數中傳入done,並且在異步鈎子完成時調用它。
describe('hooks', function() {
before(function(done) {
// runs before all tests in this block
setTimeout(() => {
done() // 2000ms之後才會執行下一個鈎子
}, 2000)
})
});
mocha默認的測試超時時間是2000ms,如果你的異步鈎子準備時間超過2000ms,請事先聲明超時時間
在瀏覽器端測試
以後補上
vscode 插件
vscode 上面有一個輔助mocha測試的插件 mocha sidebar。
- New code coverage support
- see all tests in vscode side bar menu
- git lens for running/debugging directly form the code
- decorations which shows test status(pass/fail/not run) from code
- run tests for each level hierarchy from all tests to a single test(and each describer of course)
- debug tests for each level hierarchy from all tests to a single test(and each describer of course)
- auto run tests on file save
- see tests results directly on the code
- run/debug results directly from the code
- see test errors as decoration
- NEW add context menu on folders in explorer to set subdirectory (#2).
設置使用babel-register
在vscode的首選項設置如下:
"mocha.requires": ["babel-register"]
mocha sidebar 0.20.22 版本目前只支持babel 6, 如果你使用babel 7 ,那麼你就只能在命令中運行測試
mocha --require @babel/register xxx.js
ES6 的module 語法
ES6的import 和 export 在node中並沒有實現,所以我們需要通過Babel轉換ES6的模塊語法。
npm install babel@6 babel-preset-env babel-register
//.babelrc
{
"presets": ["env"]
}
現在你可以在啓動時加入--require參數來讓使用了ES6 import/export語法的測試文件在加載時使用babel編譯。
mocha --require babel-register ./test/test.js
import _ from 'lodash'
describe('Array', function(){
it('should correct', function(){
return Promise.resolve()
})
})
如果你不使用--require參數,那麼你需要顯式使用babel-register
// index.js
require('babel-register')
require('./test.js')
// test.js
import _ from 'lodash'
describe('Array', function(){
it('should correct', function(){
return Promise.resolve()
})
})
// comman line
mocha ./index.js
babel-register 會在node 的require中注入一個鈎子,讓所有以.es6, .jsx, .js, .es作為後綴結尾的文件在require的時候都先經過babel編譯。這樣子我們在index.js require('./test.js')的時候,就已經將import 語法轉換為requrie語法了。