單元測試並不是直接就可以做的,還必須讓程式「可測試」。
問題點
要開始做單元測試時,會發現一件事情
之前的evolve.js主程式長這樣:
https://github.com/fillano/evolve/blob/8e7269d5bfccd9e616af00f87d9f2d9db80f1dd1/lib/evolve.js(太長了,請到github看)
現在把tools拆出來成為tools.js:
https://github.com/fillano/evolve/blob/13cbf9ec2629bd02e15c350564c1537cc9ba292a/lib/tools.js(還是太長)
這樣evolve.js主程式就只剩下:
var http = require('http'),
tools = require('./tools');
var count = 0;
var evolve = function(conf) {
var server = http.createServer(function(request, response) {
console.log(process.pid + '::' + ++count + ': ' + process.memoryUsage().heapUsed);
tools.dispatch(conf, request, response, function(err, realpath, data) {
if(err) {
console.log(process.pid + '::' + realpath + ' not exists.');
response.writeHead(404, {"Content-Type":"text/html"});
response.end('<h1>404: Request resource not found.</h1>');
} else {
console.log(process.pid + '::' + realpath + ' exists.');
response.writeHead(200, {
"Content-Type": data.type,
"Content-Length": data.data.length
});
response.end(data.data);
}
});
});
this.listen = function(port, addr) {
server.listen(port, addr);
return this;
};
this.host = tools.hostHandler;
};
module.exports = evolve;
一方面變得更精簡,另一方面要開始調整伺服器的細部結構時,這樣應該會更容易。
針對模組做單元測試
先對cache做簡單的測試(testCache.js):
var testCase = require('nodeunit').testCase;
module.exports = testCase({
setUp: function(cb) {
this.cache = require('../lib/cache');
this.target = {type: 'foo', value: 'bar'};
cb();
},
tearDown: function(cb) {
this.cache = null;
delete this.cache;
this.target = null;
delete this.target;
cb();
},
"test cache.regist": function(test) {
test.expect(2);
this.cache.put('foo', 'bar', this.target);
test.equal(typeof this.cache.get('foo', 'bar'), 'undefined', 'cache.get to unregisted cache type will got undefined.');
this.cache.regist('foo');
this.cache.put('foo', 'bar', this.target);
test.deepEqual(this.cache.get('foo', 'bar'), this.target, 'cache.put an object and then cache.get the object.');
test.done();
},
"test cache.del": function(test) {
test.expect(2);
this.cache.regist('none');
this.cache.put('none', 'foo', this.target);
test.deepEqual(this.cache.get('none', 'foo'), this.target, 'confirm object get from cache is matched.');
this.cache.del('none', 'foo');
test.equal(typeof this.cache.get('none', 'foo'), 'undefined', 'delete from cache and test the deleted will become undefined.');
test.done();
},
"test cache.query": function(test) {
test.expect(2);
this.cache.regist('fs');
test.equal(this.cache.query('fs', 'foo'), false, 'cache.query with non existed item will return false.');
this.cache.put('fs', 'foo', this.target);
test.equal(this.cache.query('fs', 'foo'), true, 'cache.query with existed item will return true.');
test.done();
}
});
接下來對tools.getRes做簡單的測試(testGetRes.js):
var testCase = require('nodeunit').testCase;
var path = require('path');
module.exports = testCase({
setUp: function(cb) {
this.getRes = require('../lib/tools').getRes;
cb();
},
tearDown: function(cb) {
this.getRes = null;
delete this.getRes;
cb();
},
"test tools.getRes": function(test) {
test.expect(4);
this.getRes(path.join(__dirname, '../www'), ['index.html', 'index.htm', 'default.htm'], function(err, respath, data) {
test.equal(err, false);
test.equal(data.type, 'text/html');
test.equal(Buffer.isBuffer(data.data), true);
test.ok(data.data.toString().indexOf('index')>-1);
test.done();
});
}
});
改過build.xml之後跑測試:
D:\fillano\Dropbox\Shared\evolve>ant unittest
Buildfile: D:\fillano\Dropbox\Shared\evolve\build.xml
unittest:
[exec]
[exec] testRouter.js
[exec] ok: testAddHost
[exec]
[exec] testGetRes.js
[exec] ok: test tools.getRes
[exec]
[exec] testCache.js
[exec] ok: test cache.regist
[exec] ok: test cache.del
[exec] ok: t
[exec] est cache.query
[exec]
[exec] OK: 11 assertions (23ms)
BUILD SUCCESSFUL
Total time: 0 seconds
雖然結果有奇怪的折行,不過看起來還是通過測試了。(用nodeunit跑其實不會有這個問題)
即使是單元測試,也只保證所測試的「單元」沒有問題,但是怎麼知道所有東西兜起來也沒問題呢?這就要靠整合測試了。明天再來弄吧。