# unittest-demo
## 测试框架
#### 测试接口
Mocha的BDD接口有:
- `describe()`
- `it()`
- `before()`
- `after()`
- `beforeEach()`
- `afterEach()`
#### 安装
`npm install mocha -g`
#### 编写一个稳定可靠的模块
模块具备limit方法,输入一个数值,小于0的时候返回0,其余正常返回
``` javascript
exports.limit = function (num) {
if (num < 0) {
return 0;
}
return num;
};
```
#### 目录分配
- `lib`,存放模块代码的地方
- `test`,存放单元测试代码的地方
- `index.js`,向外导出模块的地方
- `package.json`,包描述文件
#### 测试
``` javascript
var lib = require('index');
describe('module', function () {
describe('limit', function () {
it('limit should success', function () {
lib.limit(10);
});
});
});
```
#### 结果
在当前目录下执行`mocha`:
```
$ mocha
․
✔ 1 test complete (2ms)
```
## 断言库
上面的代码只是运行了代码,并没有对结果进行检查,这时候就要用到断言库了,Node.js中常用的断言库有:
- should.js
- expect.js
- chai
#### 加上断言
使用`should`库为测试用例加上断言
``` javascript
it('limit should success', function () {
lib.limit(10).should.be.equal(10);
});
```
## 需求变更
需求变更啦: `limit`这个方法还要求返回值大于100时返回100。
针对需求重构代码之后,正是测试用例的价值所在了,
它能确保你的改动对原有成果没有造成破坏。
但是,你要多做的一些工作的是,需要为新的需求编写新的测试代码。
## 异步测试
#### 测试异步回调
lib库中新增async函数:
``` javascript
exports.async = function (callback) {
setTimeout(function () {
callback(10);
}, 10);
};
```
测试异步代码:
``` javascript
describe('async', function () {
it('async', function (done) {
lib.async(function (result) {
done();
});
});
});
```
#### 测试Promise
使用should提供的Promise断言接口:
- `finally` | `eventually`
- `fulfilled`
- `fulfilledWith`
- `rejected`
- `rejectedWith`
- `then`
测试代码
``` javascript
describe('should', function () {
describe('#Promise', function () {
it('should.reject', function () {
(new Promise(function (resolve, reject) {
reject(new Error('wrong'));
})).should.be.rejectedWith('wrong');
});
it('should.fulfilled', function () {
(new Promise(function (resolve, reject) {
resolve({username: 'jc', age: 18, gender: 'male'})
})).should.be.fulfilled().then(function (it) {
it.should.have.property('username', 'jc');
})
});
});
});
```
#### 异步方法的超时支持
Mocha的超时设定默认是2s,如果执行的测试超过2s的话,就会报timeout错误。
可以主动修改超时时间,有两种方法。
#### 命令行式
`mocha -t 10000`
#### API式
``` javascript
describe('async', function () {
this.timeout(10000);
it('async', function (done) {
lib.async(function (result) {
done();
});
});
});
```
这样的话`async`执行时间不超过10s,就不会报错timeout错误了。
## 异常测试
异常应该怎么测试,现在有`getContent`方法,他会读取指定文件的内容,但是不一定会成功,会抛出异常。
``` javascript
exports.getContent = function (filename, callback) {
fs.readFile(filename, 'utf-8', callback);
};
```
这时候就应该模拟(mock)错误环境了
#### 简单Mock
``` javascript
describe("getContent", function () {
var _readFile;
before(function () {
_readFile = fs.readFile;
fs.readFile = function (filename, encoding, callback) {
process.nextTick(function () {
callback(new Error("mock readFile error"));
});
};
});
// it();
after(function () {
// 用完之后记得还原。否则影响其他case
fs.readFile = _readFile;
})
});
```
#### Mock库
Mock小模块:[`muk`](https://github.com/fent/node-muk) ,略微优美的写法:
``` javascript
var fs = require('fs');
var muk = require('muk');
before(function () {
muk(fs, 'readFile', function(path, encoding, callback) {
process.nextTick(function () {
callback(new Error("mock readFile error"));
});
});
});
// it();
after(function () {
muk.restore();
});
```
## 测试私有方法
针对一些内部的方法,没有通过exports暴露出来,怎么测试它?
``` javascript
function _adding(num1, num2) {
return num1 + num2;
}
```
#### 通过rewire导出方法
模块:[`rewire`](http://jhnns.github.com/rewire/)
```
it('limit should return success', function () {
var lib = rewire('../lib/index.js');
var litmit = lib.__get__('limit');
litmit(10);
});
```
## 测试Web应用
在开发Web项目的时候,要测试某一个API,如:`/user`,到底怎么编写测试用例呢?
使用:[`supertest`](https://github.com/visionmedia/supertest)
``` javascript
var express = require("express");
var request = require("supertest");
var app = express();
// 定义路由
app.get('/user', function(req, res){
res.send(200, { name: 'jerryc' });
});
describe('GET /user', function(){
it('respond with json', function(done){
request(app)
.get('/user')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function (err, res) {
if (err){
done(err);
}
res.body.name.should.be.eql('jerryc');
done();
})
});
});
```
## 覆盖率
测试的时候,我们常常关心,是否所有代码都测试到了。
这个指标就叫做["代码覆盖率"](http://en.wikipedia.org/wiki/Code_coverage)(code coverage)。它有四个测量维度。
> - **行覆盖率**(line coverage):是否每一行都执行了?
> - **函数覆盖率**(function coverage):是否每个函数都调用了?
> - **分支覆盖率**(branch coverage):是否每个if代码块都执行了?
> - **语句覆盖率**(statement coverage):是否每个语句都执行了?
[Istanbul](https://github.com/gotwarlost/istanbul) 是 JavaScript 程序的代码覆盖率工具。
#### 安装
`$ npm install -g istanbul`
#### 覆盖率测试
在编写过以上的测试用例之后,执行命令:
`istanbul cover _mocha`
就能得到覆盖率:
``` javascript
JerryC% istanbul cover _mocha
module
limit
✓ limit should success
async
✓ async
getContent
✓ getContent
add
✓ add
should
#Promise
✓ should.reject
✓ should fulfilled
6 passing (32ms)
================== Coverage summary ======================
Statements : 100% ( 10/10 )
Branches : 100% ( 2/2 )
Functions : 100% ( 5/5 )
Lines : 100% ( 10/10 )
==========================================================
```
这条命令同时还生成了一个 coverage 子目录,其中的 coverage.json 文件包含覆盖率的原始数据,coverage/lcov-report 是可以在浏览器打开的覆盖率报告,其中有详细信息,到底哪些代码没有覆盖到。
![覆盖率html](http://xia-dev.b0.upaiyun.com/eac87dbf-4e4b-426e-80ac-7c50e1b9a1cb.jpg)
上面命令中,`istanbul cover` 命令后面跟的是 `_mocha` 命令,前面的下划线是不能省略的。
因为,[mocha 和 _mocha 是两个不同的命令](https://github.com/gotwarlost/istanbul/issues/44),前者会新建一个进程执行测试,而后者是在当前进程(即 istanbul 所在的进程)执行测试,只有这样, istanbul 才会捕捉到覆盖率数据。其他测试框架也是如此,必须在同一个进程执行测试。
如果要向 mocha 传入参数,可以写成下面的样子。
```
$ istanbul cover _mocha -- tests/test.sqrt.js -R spec
```
上面命令中,两根连词线后面的部分,都会被当作参数传入 Mocha 。如果不加那两根连�
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
软件测试_基于node.js开发的单元测试实例.zip (19个子文件)
软件测试_基于node.js开发的单元测试实例
.travis.yml 37B
Makefile 3KB
package.json 444B
test
mocha.opts 57B
should.test.js 714B
index.test.js 1KB
web.test.js 716B
index.js 495B
README.md 9KB
coverage
lcov-report
sorter.js 5KB
sort-arrow-sprite.png 209B
index.html 3KB
prettify.css 676B
base.css 5KB
prettify.js 17KB
unittest-demo
index.js.html 4KB
index.html 3KB
lcov.info 416B
coverage.json 2KB
共 19 条
- 1
资源评论
DdddJMs__135
- 粉丝: 962
- 资源: 271
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功