Guide 開髮指南

美好生活從測試開始

不寫自動測試用例的程序員不是一個好的測試工程師。我們鼓勵所有的項目在啟動最初,就建立完整的自動化測試用例。隨著項目的發展,前期的投入會得到數百倍的回報。

我們延續上一小節的例子,來看一下一個如何使用fibjs 編寫測試用例。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const http = require('http'); const path = require('path'); var hello_server = { '/:name(fibjs.*)': (req, name) => { req.response.write('hello, ' + name + '. I love you.'); }, '/:name': (req, name) => { req.response.write('hello, ' + name); } }; var root_server = { '/hello': hello_server, '/bonjour': hello_server, '*': http.fileHandler(path.join(__dirname, 'web')) }; var svr = new http.Server(8080, root_server); svr.start();

一個空的測試框架

我們先從一個最基礎的測試框架開始搭建:

1 2 3 4 5 6 7 8 9 10
var test = require('test'); test.setup(); describe('hello, test', () => { it('a empty test', () => { }); }); test.run();

保存為 test.jsfibjs test.js

1 2 3 4
hello, test √ a empty test √ 1 tests completed (0ms)

開始測試服務器

因為我們需要測試http 服務器,所以我們需要先啟動服務器。測試用例會向服務器發出請求,然後測試請求結果,來判斷服務器是否符合需求:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
var test = require('test'); test.setup(); var http = require('http'); describe('hello, test', () => { it('hello, fibjs', () => { var r = http.get('http://127.0.0.1:8080/hello/fibjs'); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), 'hello, fibjs. I love you.'); }); }); test.run();

在這段代碼中,我們通過驗證http.get 的結果是否是我們期望的結果,來判斷服務器邏輯是否正常。按照這個示例,我們可以很快完成一組測試,我們同時優化了一下代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
var test = require('test'); test.setup(); var http = require('http'); function test_get(url, rep) { var r = http.get('http://127.0.0.1:8080' + url); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), rep); } describe('hello, test', () => { it('hello, fibjs', () => { test_get('/hello/fibjs', 'hello, fibjs. I love you.'); }); it('hello, fibjs*', () => { test_get('/hello/fibjs-great', 'hello, fibjs-great. I love you.'); }); it('hello, JavaScript', () => { test_get('/hello/JavaScript', 'hello, JavaScript'); }); it('hello, v8', () => { test_get('/hello/v8', 'hello, v8'); }); }); test.run();

用例的分組管理

下面我們來增加bonjour 的測試,雖然bonjour 和hello 是同一組服務,但是因為路徑發生了變化,我們同樣需要驗證服務的正確性,這一次,為了能更好地管理用例,我們對測試用例進行了分組,同時,因為hello 和bonjour 的測試內容是相同的,我們再次優化了代碼,用同一套代碼測試兩組服務:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
var test = require('test'); test.setup(); var http = require('http'); function test_get(url, rep) { var r = http.get('http://127.0.0.1:8080' + url); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), rep); } describe('hello, test', () => { function test_hello(hello) { describe(hello + ' test', () => { it('fibjs', () => { test_get('/' + hello + '/fibjs', 'hello, fibjs. I love you.'); }); it('fibjs*', () => { test_get('/' + hello + '/fibjs-great', 'hello, fibjs-great. I love you.'); }); it('JavaScript', () => { test_get('/' + hello + '/JavaScript', 'hello, JavaScript'); }); it('v8', () => { test_get('/' + hello + '/v8', 'hello, v8'); }); }); } test_hello('hello'); test_hello('bonjour'); }); test.run();

通過用例分組,我們可以更加清晰地查看測試結果,也可以很方便地跳過和單獨測試一組用例,加快開發測試速度。以下是這一輪測試的結果:

1 2 3 4 5 6 7 8 9 10 11 12 13
hello, test hello test √ fibjs √ fibjs* √ JavaScript √ v8 bonjour test √ fibjs √ fibjs* √ JavaScript √ v8 √ 8 tests completed (3ms)

根據我們的服務器設計,我們還有一組靜態文件服務,按照上面的示例,相信你很快可以補寫出這部分測試用例。

一鍵測試

經過上面的介紹,我們已經可以很快建立起測試用例了。但是為了使用這個測試腳本,必須先啟動服務器,這樣很不方便,我們希望運行 我們可以用以下代碼來實現:test.js

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
var test = require('test'); test.setup(); var http = require('http'); var coroutine = require('coroutine'); coroutine.start(() => { run('./main.js'); }); coroutine.sleep(100); function test_get(url, rep) { var r = http.get('http://127.0.0.1:8080' + url); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), rep); } describe('hello, test', () => { function test_hello(hello) { describe(hello + ' test', () => { it('fibjs', () => { test_get('/' + hello + '/fibjs', 'hello, fibjs. I love you.'); }); it('fibjs*', () => { test_get('/' + hello + '/fibjs-great', 'hello, fibjs-great. I love you.'); }); it('JavaScript', () => { test_get('/' + hello + '/JavaScript', 'hello, JavaScript'); }); it('v8', () => { test_get('/' + hello + '/v8', 'hello, v8'); }); }); } test_hello('hello'); test_hello('bonjour'); }); process.exit(test.run());

這段代碼的第6~10 行里,我們增加了一段啟動 main.js

代碼覆蓋檢查

好的測試用例需要考慮測試用例需要覆蓋業務的每一個分支,以確定業務執行正確,此時可以使用代碼覆蓋檢查,來確定測試是否完整。

這個過程很簡單,只需要在測試的時候增加--cov 參數即可:

1
fibjs --cov test

測試完成後,會在當前目錄生成一個fibjs-xxxx.lcov 的日誌文件,此時需要分析日誌並生成報告:

1
fibjs --cov-process fibjs-xxxx.lcov out

便可以在out 目錄生成一組分析報告。進入目錄查閱,可以看到以下頁面:點擊 covmain.jsmain.js

👉 【