有羣友問到Express怎麼作 單元測試/覆蓋率測試,這是上篇所遺漏的,特此補上javascript
作 Express Web 測試首先要面對的問題是在哪端進行測試:php
咱們須要對Express的路由作覆蓋率測試,顯然,咱們會選擇在服務端進行測試。這意味着:每一個case須要訪問的express application 不是這樣預先啓動的:html
1
2
3
4
|
var
express = require(
'express'
);
var
app = express();
//some router code...
app.listen(3000);
|
咱們須要一個工具能建立啓動express application,並 Mock 對它的請求,只有這樣,測試框架才能檢測到路由方法內部代碼執行的路徑和覆蓋率。java
這裏,咱們引入supertest 作爲 mock 工具。node
SuperTest 是TJ大神的又一款做品:基於SuperAgent ,提供對HTTP測試的高度抽象。所謂高度抽象的意思是:能嵌入各種測試框架,提供語義良好的斷言。git
來看段 SuperTest結合 Mocha的代碼:github
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var
app = require(
'../app'
);
var
request = require(
'supertest'
);
describe(
'router testing'
,
function
() {
it(
'site root response'
,
function
(done) {
request(app)
.get(
'/'
)
.expect(
'Content-Type'
,
'text/html; charset=utf-8'
)
.expect(200)
.end(
function
(err, res){
if
(err)
throw
err;
done();
});
});
|
簡單易懂,重點是它驅動了express。shell
代碼覆蓋(Code coverage)是軟件測試中的一種度量,描述程式中源代碼被測試的比例和程度,所得比例稱爲代碼覆蓋率。express
如下是幾個覆蓋率指標:npm
對指標的偏好可說是見仁見智,好比大名鼎鼎的 coveralls.io 就以行覆蓋率(Line coverage) 做爲給項目頒發badge的首選指標。
咱們須要的,是一個能根據測試用例得出覆蓋率指標的工具:
istanbul 就是這樣一個工具,能產生 Statements/Lines/Functions/Branches 等指標報表,並以各類格式導出。
值得稱道的是,istanbul 能和 Mocha 很好的集成,如:把測試用例統一放置在 /test下,要對它們進行測試並生成覆蓋率報表,能夠在 package.json 中添加這樣的配置:
1
2
3
4
|
"scripts"
: {
"test"
:
"mocha --recursive --timeout 500000 test/ --bail"
,
"test-cov"
:
"node node_modules/istanbul-harmony/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- --timeout 500000 --recursive test/ --bail"
}
|
只須要進行測試時,在項目目錄下使用命令:
1
|
npm
test
|
須要進行測試並追加覆蓋率報表時,在項目目錄下使用命令:
1
|
npm run-script
test
-cov
|
在測試部分完成後,會獲得以下報表信息(在項目 /coverage 目錄下,會生成lcov.info 等覆蓋率數據文件:
mock 工具備了, 測試框架和覆蓋率工具也有了,就差實戰了。下面舉個粟子看看怎麼作 Express 的覆蓋率測試:
1
|
npm
install
-g mocha
|
1
|
npm
install
-g istanbul
|
1
|
npm
install
-g express
|
1
|
express -e express-coverage
|
npm install 安裝須要的包:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
{
"name"
:
"express-coverage"
,
"version"
:
"0.0.1"
,
"scripts"
: {
"test"
:
"mocha test/ --bail"
,
"test-cov"
:
"node node_modules/istanbul-harmony/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- test/"
},
"dependencies"
: {
"express"
:
"~4.9.0"
,
"body-parser"
:
"~1.8.1"
,
"cookie-parser"
:
"~1.3.3"
,
"morgan"
:
"~1.3.0"
,
"serve-favicon"
:
"~2.1.3"
,
"debug"
:
"~2.0.0"
,
"ejs"
:
"~0.8.5"
,
"istanbul-harmony"
:
"*"
,
"should"
:
"*"
,
"mocha"
:
"*"
,
"mocha-lcov-reporter"
:
"*"
,
"supertest"
:
"*"
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
var
express = require(
'express'
);
var
router = express.Router();
router.get(
'/'
,
function
(req, res) {
var
msg =
'no user'
;
res.send(msg);
});
router.get(
'/:id'
,
function
(req, res) {
var
msg =
'user: '
+ req.params.id;
res.send(msg);
});
module.exports = router;
|
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
|
var
should = require(
'should'
);
var
app = require(
'../app'
);
var
request = require(
'supertest'
);
describe(
'router testing'
,
function
() {
it(
'users have not id response'
,
function
(done) {
request(app)
.get(
'/users'
)
.expect(
'Content-Type'
,
'text/html; charset=utf-8'
)
.expect(200)
.end(
function
(err, res){
if
(err)
throw
err;
should.exist(res.text);
done();
});
});
it(
'users have id response'
,
function
(done) {
request(app)
.get(
'/users/1/'
)
.expect(
'Content-Type'
,
'text/html; charset=utf-8'
)
.expect(200)
.end(
function
(err, res){
if
(err)
throw
err;
should.exists(res.text);
done();
});
});
});
|
npm run-script test-cov
獲得覆蓋率報表:
1
2
3
4
5
6
7
8
9
10
11
12
|
app.use(
function
(req, res, next) {
var
err =
new
Error(
'Not Found'
);
err.status = 404;
next(err);
});
app.use(
function
(err, req, res, next) {
res.status(err.status || 500);
res.render(
'error'
, {
message: err.message,
error: {}
});
});
|
1
2
3
4
5
6
7
8
9
|
it(
'404 response'
,
function
(done) {
request(app)
.get(
'/non/'
)
.expect(404)
.end(
function
(err, res){
if
(err)
throw
err;
done();
});
});
|
npm run-script test-cov
查看覆蓋率報表,咱們能看到進步 :) 找到合適的 Mock工具和測試框架並進行整合,Web測試及覆蓋率報表獲取的思路大抵如此。關於測試框架的各類參數組合和花樣玩法,還有不少有意思的功能(好比和 Travis-CI、Coveralls.io 等公共服務集成,在倉庫上展現項目狀態徽章),本文再也不贅述,有興趣的可加node學習交流羣一塊兒探討。