前言
到了开发的后期,测试工作往往是重中之重,但是测试本身又十分繁琐与复杂。对于使用js的朋友,对于我接下来要讲的内容绝对不会陌生,对,就是大名鼎鼎的摩卡!由于为我的好友开发的后端框架Zeta做测试工作,所以开始接触这一类测试工具和测试流程,就把我的学习经验分享给大家吧。
mocha
mocha的使用方法十分简单,就是两个语句describe和it
describe
js
describe('req.get',function(){ describe('res.json',function(){ }); });
被describe的回调所包裹的是一个测试流程,使用describe可以很好地为测试表明目的和区分层次
it
js
describe('Array.index',function(){ it('should return -1 when not found',function(){ var tmp=[1,2,3]; tmp.indexOf(4).should.equal(-1); }); });
it的第一个参数是个字符串,你可以把它看做是你测试样例的期望结果,其实没有什么实际意义,不会对测试样例的运行有什么影响。
上面的例子是对于同步的,如果有异步回调怎么办呢?
js
describe('db.save',function(){ it('should save the doc',function(done){ doc.save(function(err,doc){ if(err) done(err); if(!doc) done(err); done(); }); }); });
done是链的最后一个步骤,调用done既不会往下执行,done(err)则说明失败。
chai
chai是一个断言工具,提供了一些比较受欢迎的断言写法,这里主要介绍两个,should和expect。
should
js
var should=require('chai').should(); res.text.should.equal('hi,world'); req.path.should.include('users'); foo.should.have.length(3);
从上面的例子大家可以领会should的写法了。
expect
js
var expect=require('chai').expect; expect(foo).to.be.a('string'); expect(foo).to.equal('bar'); expect(foo).to.have.length(3); expect(beverages).to.have.property('tea').with.length(3);
chai的使用十分人性化,符合自然语言的规律,就不多提了。
supertest
对后端测试的时候难免会发起请求,supertest为我们提供了这样的功能。
js
var request=require('supertest'); request(app). get('/foo'). expect(200). expect('Content-Type','application/json'). end(function(err,res){ if(err) throw err; });
要模拟异步ajax怎么办呢
js
//json上传 request(app). post('/foo'). send({key:'value'}). expect(200); //表单提交 request(app). post('/foo'). type('form'). send({key:value}); //上传文件 request(app). post('/foo'). attach('field','filepath'). ....
要设置一些东西怎么办呢?
js
request(app). post('/hh'). send({key:val}). set('Accept-laguange','zh-cn'). set('Cookie',['user=suemi','passwd=*******']). ...
supertest主要使用的就是expect和end了,通过例子,大家也很清楚基本的用法了,对于详细的API可以参考官网。
完整示例
最后给大家带来一个我自己写的完整示例。
js
var Zeta=require('../../'), assert=require('assert'), request=require('supertest'), demo=Zeta.module('demo',[]), should=require('chai').should(); demo.load(); describe('singleHandler',function(done){ it('should get hello',function(){ demo.handler('h1',function($scope){ $scope.res.writeHead(200,{'Content-Type':'text/plain'}); $scope.res.write('hello,world'); $scope.res.end(); }); demo.get('/test','h1'); request(demo.server()) .get('/test') .expect(200) .end(function(err,res){ if(err) throw err; res.text.should.equal('hello,world'); }); }); it('should cover the previous one',function(done){ demo.handler('h1',function($scope){ $scope.res.writeHead(200,{'Content-Type':'text/plain'}); $scope.res.write('hi,world'); $scope.res.end(); }); request(demo.server(true)). get('/test'). expect(200). end(function(err,res){ if(err) done(err); res.text.should.equal('hi,world'); done(); }); }); });
测试效果截图如下
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。