有群友问到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学习交流群一块儿探讨。