關於單元測試的想法
對於一些比較重要的專案,每次更新程式碼之後總是要自己測好久,擔心一旦上線出了問題影響的服務太多,此時就希望能有一個比較規範的測試流程。在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中加上
<script src="http://chaijs.com/chai.js"></script>
index.html內容如下:
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="http://chaijs.com/chai.js"></script>
<script src="mocha.js"></script>
<script>mocha.setup('bdd');</script>
<script src="tests.js"></script>
<script>
mocha.run();
</script>
</body>
</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 <k=v,k2=v2,...> reporter-specific options
-R, --reporter <name> 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 <pattern> 只執行滿足 <pattern>格式的用例
-f, --fgrep <string> 只執行含有 <string> 的用例
-gc, --expose-gc 展示gc回收的log
-i, --invert 讓 --grep 和 --fgrep 的匹配取反
-r, --require <name> require一下<name>指定的模組
-s, --slow <ms> 指定slow時間(單位ms,預設75ms)
-t, --timeout <ms> 指定超時時間(單位ms,預設2000ms)
-u, --ui <name> 指定user-interface (bdd|tdd|exports)
-w, --watch 觀察用例檔案變化,並重新執行
--check-leaks 檢測未回收global變數洩露
--compilers <ext>:<module>,... 用指定的模組來編譯檔案
--debug-brk 啟用node的debug模式
--delay 等待非同步的用例集(見前邊的)
--es_staging enable all staged features
--full-trace display the full stack trace
--globals <names> 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 <path> 定義option檔案路徑
--prof 顯示統計資訊
--recursive 包含子目錄
--reporters 展示可用報告
--retries 設定失敗用例重試次數
--throw-deprecation 每次呼叫deprecated函式的時候都丟擲一個異常
--trace 顯示函式呼叫棧
--trace-deprecation 啟用的時候顯示呼叫棧
--watch-extensions <ext>,... --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
,結果:
<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>
自己新增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()
函式來執行測試
<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>
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目錄下
編輯器外掛
TEXTMATE、JETBRAINS (IntelliJ IDEA, WebStorm, etc.) 等編輯器均有支援mocha測試的外掛,需要使用的話請自行查閱。
使用mocha的專案示例
這個是官方文件地址:http://mochajs.org/
轉自我的個人站:http://zoucz.com/