ååããã¬ãŒã ã¯ãŒã¯ãšããŠexpressjsã䜿çšãããã³ãã¬ãŒããšã³ãžã³ãšããŠjadeã䜿çšããŠãnodejsã§ã¢ããªã±ãŒã·ã§ã³ãäœæããããšã«ã€ããŠæžããŸããã ä»åã¯ããµãŒããŒåŽã®ãã¹ãã«çŠç¹ãåœãŠãããšæããŸãã
ãã¹ãã«ã¯ã次ã®ãã®ã䜿çšããŸãã
-Mocha-ãã¹ããèšè¿°ããç°¡åãã€ç°¡åã«å®è¡ã§ãããã¬ãŒã ã¯ãŒã¯ã ããŸããŸãªããŒãžã§ã³ã®ã¬ããŒããçæãããã¹ãããããã¥ã¡ã³ããäœæããæ¹æ³ãç¥ã£ãŠããŸãã
-Should- ãæ¿èªãã®ã¹ã¿ã€ã«ã®ãã¹ãçšã©ã€ãã©ãª
ïŒæ£ããååãèŠã€ãããŸããã§ããïŒ-SuperTest -
nodejsã§ HTTPãµãŒããŒããã¹ãããããã®ã©ã€ãã©ãª
-jscoverage-ãã¹ãã§ã³ãŒãã«ãã¬ããžãè©äŸ¡ãã
ãã¹ãŠããŒãããäœæããããã§ã¯ãããŸããããåã®èšäºã®
ã¢ããªã±ãŒã·ã§ã³ããã¹ãã§ã©ããããapp2ãã©ã«ããŒã«å®å
šã«ã³ããŒããããšã«ããŸããã
ãŸããå¿
èŠãªã¢ãžã¥ãŒã«ãpackage.jsonãã¡ã€ã«ã«è¿œå ããŸãã å¿
èŠãªã®ã¯ãmochaãshouldãsupertestã§ãã
package.json{ "name": "app2", "version": "0.0.0", "author": "Evgeny Reznichenko <kusakyky@gmaill.com>", "dependencies": { "express": "3", "jade": "*", "should": "*", "mocha": "*", "supertest": "*" } }
npm iã³ãã³ããå®è¡ããŠãå¿
èŠãªãã¹ãŠã®ã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ããŸãã
jscoverageãã€ã³ã¹ããŒã«ããŸãïŒUbuntu
sudo apt-get install jscoverageã®äž ïŒã
次ã«ããããžã§ã¯ãã®ã«ãŒãã«libãã£ã¬ã¯ããªãäœæããããã«app.jsãã³ããŒããŸããããã¯ããã¹ãŠã®ã¹ã¯ãªãããã«ãã¬ããžãã¹ãã§ç°¡åã«ã«ããŒããããã«å¿
èŠã§ãã
app.jsãã¡ã€ã«ãç·šéããŠãµãŒããŒãå€éšã«ãšã¯ã¹ããŒããããããžã§ã¯ãã®ã«ãŒãã«index.jsãã¡ã€ã«ãäœæããŸããããã«ããããµãŒããŒãæ¥ç¶ããããœã±ããã«ãã³ã°ã¢ããããŸãã ãŸãããã¥ãŒãšãããªãã¯ãã£ã¬ã¯ããªãžã®ãã¹ãä¿®æ£ããããšãå¿ããªãã§ãã ããã
次ã®ããã«ãªããŸãã
index.js var app = require('./lib/app.js'); app.listen(3000);
lib / app.js var express = require('express'), jade = require('jade'), fs = require('fs'), app = express(), viewOptions = { compileDebug: false, self: true };
app.jsãã¡ã€ã«ãèŠãŠã¿ãŸãããã3ã€ã®è«çéšåã«åãããŠããã®ã¯æããã§ãã
-æåã®éšåã§ã¯ãããŒã¿ã¢ãã«ãæäœããããžãã¯å
šäœãåãäžããŸãã
-2çªç®ã®éšåããã¹ãŠã®è£å©ãŠãŒãã£ãªãã£ã§ã¯ã
ããŒãžæ©èœã®ã¿ããããŸãã
-3çªç®ã¯ãµãŒããŒèªäœã«ãªããŸã
ç§ãã¡ã¯åžæã決ããã®ã§ããã¹ãã®äœæãå§ããŸãããããã¹ããå®è¡ããã®ã«äŸ¿å©ãªMakefileãæåã«äœæãããããžã§ã¯ãã®ã«ãŒãã«é
眮ããŸãã
ã¡ã€ã¯ãã¡ã€ã« MOCHA = ./node_modules/.bin/mocha test: @NODE_ENV=test $(MOCHA) \ -r should \ -R spec .PHONY: test
--r-Mochaãshouldã©ã€ãã©ãªãæ¥ç¶ããããšã瀺ããŸã
--R-ãã¹ãã¬ããŒãã衚瀺ãã圢åŒã瀺ããŸãã ã¬ããŒãã«ã¯ããã€ãã®ã¿ã€ãããããããã¯æ¬¡ã®ããã«ãªããŸãã
ãããŒã«ãã®ãã¹ã
ããã©ã«ãã§ã¯ãMochaã¯ãã¹ããã£ã¬ã¯ããªãããã¹ããå®è¡ããããããã®ãããªãã£ã¬ã¯ããªãäœæããŠæåã®ãã¹ããèšè¿°ããŸãã
ãããŠããããŒã«ãã䜿çšããŠãã¹ããéå§ããå°ããªèšç»ãäœæããŸãã
-ãããŒã«ãã§ã¯ããŒãžé¢æ°ã§ããå¿
èŠããããŸã
-ããŒãžæ©èœã¯ã2ã€ã®ãªããžã§ã¯ãã1ã€ã«ããŒãžããå¿
èŠããããŸã
-ããã«ãæåã«éä¿¡ããããªããžã§ã¯ãã¯å±éããå¿
èŠãããã2çªç®ã®ãªããžã§ã¯ãã¯
-颿°ã¯2çªç®ã®ãªããžã§ã¯ãã倿ŽããŠã¯ãªããŸãã
Mochaã®BDDãã¹ãã¯ã
describeïŒïŒãããã¯ã§å§ãŸããŸã
ã ããã¹ãèªäœã¯
itïŒïŒãããã¯ã«æžã蟌ãŸããŸã
ã describeïŒïŒãããã¯å
ã«é
眮ããå¿
èŠããããŸãã describeïŒïŒãããã¯ãçžäºã«ãã¹ãããããšãã§ããŸãã ããã¯ã䜿çšã§ããŸãïŒbeforeïŒïŒãafterïŒïŒãbeforeEachïŒïŒãafterEachïŒïŒã ããã¯ã¯ãdescribeïŒïŒãããã¯å
ã«ãèšè¿°ããå¿
èŠããããŸãã åœã®ããŒã¿ããŒã¹ãæäœããã¢ãã«ããã¹ããããšãã®ããã¯ã«ã€ããŠè©³ãã説æããŸãã
ãã¹ããã£ã¬ã¯ããªã§ãtools.jsãã¡ã€ã«ãäœæããtools.mergeã®ãã¹ããèšè¿°ããŸãã
test / tools.js var tools = require('../lib/tools/index.js'); describe('tools', function () {
ããã§ãã¹ããå®è¡ãããšãããŒã«ã¢ãžã¥ãŒã«ãæ¥ç¶ããæ®µéã§ãšã©ãŒã«é¥ããŸãããããã¯æ£åžžã§ããããã®ã¢ãžã¥ãŒã«ã¯ãŸã ãããŸããã ãã¡ã€ã«lib / tools / index.jsãäœæããããã«lib / app.jsãã
ããŒãžé¢æ°ã³ãŒãã転é
ããŸãã
makeãã¹ããå®è¡ãã4ã€ã®ãã¹ããã¹ãŠãå§åãããããšã確èªããŸãã
ãªããªã æåã®ãã¹ããå§åããããšãããŒãžæ©èœãããŒã«ã¢ãžã¥ãŒã«ãããšã¯ã¹ããŒããããªãããšãæããã«ãªããŸãã ãšã¯ã¹ããŒãã远å ãããã¹ããå床å®è¡ãããšããã¹ãŠãæ£åžžã«åäœããããã«ãªããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®æ®ããããã«ãã¹ãããåã«ãã«ãã¬ããžãã¹ãã远å ããŸãã
ãã©ã¡ãŒã¿ãŒ
--encoding = utf8ããã³
--no-highlightã 䜿çšããŠjscoverageã®å®è¡ã远å ããçä¿¡ãã£ã¬ã¯ããªãŒãšããŠ
libããçºä¿¡ãã£ã¬ã¯ããªãŒãšããŠ
lib- covãæå®ããŸãã ããã§ãã«ãã¬ããžãã¹ãã®Mochaèµ·åã远å ããç°å¢å€æ°
COVERAGE = 1ãèšå®ããã¬ããŒã¿ãŒãšããŠ
html-covãæå®ããŠãã«ãã¬ããžãã¹ãã®çµæãå«ãçŸããhtmlããŒãžãååŸããŸãã
ã¡ã€ã¯ãã¡ã€ã« MOCHA = ./node_modules/.bin/mocha test: @NODE_ENV=test $(MOCHA) \ -r should \ -R spec test-cov: lib-cov @COVERAGE=1 $(MOCHA) \ -r should \ -R html-cov > coverage.html lib-cov: clear @jscoverage --encoding=utf8 --no-highlight lib lib-cov clear: @rm -rf lib-cov coverage.html .PHONY: test test-cov clear
ãã¹ãã«æ»ã£ãŠãäžçªäžã®è¡ã眮ãæããŸãããã
var tools = require('../lib/tools/index.js');
ã«
var tools = process.env.COVERAGE ? require('../lib-cov/tools/index.js') : require('../lib/tools/index.js');
ããã ãã§ã ããã§
make test-covãå®è¡ã§ããŸãã coverage.htmlãã¡ã€ã«ããããžã§ã¯ãã«ãŒãã«è¡šç€ºãããŸããã«ãã¬ããžãã¹ãã®çµæããã¡ã€ã«ã¯èªå·±å®çµåã§ããããã©ãŠã¶ã§ããã«éãããšãã§ããŸãã
ãšã³ããªã1ã€ããªãã£ãè¡ã¯èµ€ã§è¡šç€ºãããŸããã€ãŸãããã®å Žæã¯ãã¹ãã®å¯Ÿè±¡å€ã§ãã åãã¡ã€ã«ã®å²åãšããŠã®ãã¹ãç¯å²ã®äžè¬çãªçµ±èšãæäŸãããŸãã
ããŠããã¹ãç°å¢ã¯æ§æãããŠããŸãããããŒã¿ããŒã¹ãšãµãŒããŒã®ãã¹ããèšè¿°ããããšã¯æ®ã£ãŠããŸãã
ããŒã¿ããŒã¹ã§ã®äœæ¥ã®ãã¹ã
ã¢ãã«ããã¹ãããããã®ã³ãŒããæžããŸãã ãŸããæ©èœã決å®ããŸãããã
1ïŒUserãšUserListã®2ã€ã®ã¢ãã«ãå¿
èŠã§ã
2ïŒãŠãŒã¶ãŒã¢ãã«ã«ã¯ã¡ãœãããå¿
èŠã§ãã
-find-颿°ã¯ãUserListåã®ãªããžã§ã¯ããæã€ãŠãŒã¶ãŒã®ãªã¹ããè¿ããŸãïŒäœããªãå Žåã§ãïŒ
-findById-颿°ã¯IDã§ãŠãŒã¶ãŒãæ€çŽ¢ããçµæãUseråã®ãªããžã§ã¯ããšããŠè¿ããããã®IDãæã€ãŠãŒã¶ãŒãããªãå Žåã¯äœãè¿ããªã
-ä¿å-颿°ã¯ãŠãŒã¶ãŒãä¿åããå¿
èŠãããããšã©ãŒã®å Žåã¯errãè¿ããŸã
-toJSON-颿°ã¯ãUseråã®ãªããžã§ã¯ããjsonã«ãã£ã¹ããã
3ïŒUserListã¢ãã«ã«ã¯toJSONã¡ãœããã®ã¿ãå¿
èŠã§ã
ãã¹ãã³ãŒã var should = require('should'), db = process.env.COVERAGE ? require('../lib-cov/models/db.js') : require('../lib/models/db.js'), models = process.env.COVERAGE ? require('../lib-cov/models/index.js') : require('../lib/models/index.js'), User = models.User, UserList = models.UserList; describe('models', function () {
ã³ãŒãã«ã¯ã³ã¡ã³ããä»ããŠãããããç¹å®ã®ãã€ã³ãã«ã®ã¿çŠç¹ãåœãŠãŸãã
before(function () { db.regen(); });
ãã®ã³ãŒãã¯ããã¹ãã®éå§æã«äžåºŠåŒã³åºãããŸãã ããã§ã¯ãããŒã¿ããŒã¹ã«æ¥ç¶ããŠãã¹ãããŒã¿ãå
¥åã§ããŸããå®éã®ããŒã¿ããŒã¹ã¯ãªããããregenã¡ãœãããåŒã³åºãã ãã§ãããŒã¿ããŒã¹ããã¹ãããŒã¿ã§åæåããŸãã
ããŒã¿ããŒã¹ã§ã®äœæ¥ã¯éåæã¹ã¿ã€ã«ã§å®è¡ããããšããäºå®ã«æ³šæãæã䟡å€ããããŸããéåæã¡ãœããããã¹ããããšãããããã¯ãã¹ããå®äºããããã«
doneïŒïŒã¡ãœãããåŒã³åºãå¿
èŠããããŸãããšã©ãŒã®å Žåããšã©ãŒãæž¡ãå¿
èŠããããŸãã æç¢ºã«ããããã®ã³ãŒãïŒ
...
ããã§ã¯å§ããŸãããã libãã£ã¬ã¯ããªã§ãã¢ãã«ãæäœããããã®æ©èœãå®è£
ãããã¢ãã«ãã£ã¬ã¯ããªãäœæããŸãã
ã¢ãã«/ user.js var util = require('util'), db = require('./db.js'), UserList = require('./userlist.js'), users = db.users; var User = module.exports = function User(opt) { this.id = users.length; this.name = opt.name; this.age = opt.age; this.sex = opt.sex; this.isNew = true; } function loadFromObj(obj) { var user = new User(obj); user.id = obj.id; user.isNew = false; return user; } User.find = function (fn) { var i, l = users.length, list; if (l) { list = new UserList(); for (i = 0, l; l > i; i += 1) { list.push(loadFromObj(users[i])); } } fn(null, list); }; User.findById = function (id, fn) { var obj = users[id], user; if (obj) { user = loadFromObj(obj); } fn(null, user); }; User.prototype.save = function (fn) { var err;
ã¢ãã«/ userlist.js var util = require('util'); var UserList = module.exports = function UserList() { Array.apply(this) } util.inherits(UserList, Array); UserList.prototype.toJSON = function () { var i, l = this.length, arr = new Array(l); for (i = 0; l > i; i += 1) { arr[i] = this[i].toJSON(); } return arr; };
ã¢ãã«/ index.js exports.User = require('./user.js'); exports.UserList = require('./userlist.js');
ãŠãŒã¶ãŒã¢ãã«æ¥ç¶ã远å ããããšã§lib / app.jsã³ãŒãã調æŽãããããä»ããŠãŠãŒã¶ãŒãšã®ãã¹ãŠã®äœæ¥ãè¡ããŸãã
lib / app.js var ... User = require('./models/index.js').User, ... ... app.get('/users', function(req, res, next){ User.find(function (err, users) { if (err) { next(err); } else { res.render('index', { users: users.toJSON() }); } }); }); app.get('/users/profile', function(req, res, next){ var id = req.query.id; User.findById(id, function(err, user) { if (user) { res.render({ user: user.toJSON() }); } else { next('Not found'); } }); }); ...
ã¢ããªã±ãŒã·ã§ã³ããã¹ããã
ãã¹ãã§ã«ããŒãããªãæåŸã®éšåããããŸããã ããã¯çŽæ¥HTTPãµãŒããŒã§ãã ããã§ã¯ã4ã€ã®ç¶æ³ã®ã¿ãããªãŒãºããŠãã¹ãããããšã«ããŸããã
1ïŒãããéåžžã®ãªã¯ãšã¹ãã§ããå Žåãçãã¯htmlã«æ¥ãå¿
èŠããããŸã
2ïŒãããajaxã®å Žåãçãã¯jsonã«æ¥ãå¿
èŠããããŸã
3ïŒãµã€ãã®ã«ãŒããžã®GETãªã¯ãšã¹ãã¯ãã¿ã€ãã«ã«å€ãMy siteããå«ãŸããããŒãž/ãªããžã§ã¯ããè¿ãå¿
èŠããããŸã
ã¹ãŒããŒãã¹ãã©ã€ãã©ãªã®ãããã§ããã®ãããªãã¹ãã®äœæã¯ç°¡åã§ç°¡åã§ãã
test / app.js var request = require('supertest'), app = process.env.COVERAGE ? require('../lib-cov/app.js') : require('../lib/app.js'); describe('Response html or json', function () {
requestïŒïŒã§ãhttp.Serverã®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯èŠæ±ãå®è¡ãã颿°ãæž¡ãå¿
èŠããããŸãã SuperTestã¯
SuperAgentã䜿çšããŠãµãŒããŒãšå¯Ÿè©±ããããããã¹ãŠã®æ©èœã䜿çšããŠãµãŒããŒãžã®ãªã¯ãšã¹ããäœæã§ããŸãã å¿çã®æ€èšŒã¯ã
expectïŒïŒé¢æ°ã§ããŸãã¯ãã³ãã©ãŒé¢æ°ã
endïŒïŒã«æž¡ãããšã§èŠæ±ã®çµæãšããŠçŽæ¥å®è¡ã§ããŸãã
ãããã«
ã¢ããªã±ãŒã·ã§ã³ã®ãã¹ããæžãã®ã¯ãšãŠãç°¡åã§ãïŒãããŠå¿
èŠã§ããïŒã ç§ã®ãã¹ãçšã®å°ããªãµã³ãã«ã³ãŒãã§ãããã¹ãã³ãŒãèªäœãããå€ãã®ããšã倿ããŸãããããããã®ãã¹ãã§ããäžå®å
šã§ãããããšãã°ã2人ã®ãŠãŒã¶ãŒãåæã«äœæããŠä¿åããå Žåããšã©ãŒã¯ãã¹ãã§ã«ããŒãããŸããã ã«ãã¬ããžãã¹ãã¯ããŠãŒã¶ãŒã¢ãã«ãæ°ãããŠãŒã¶ãŒãä¿åãããå Žæã®ãã¹ãã§ã«ããŒãããããšã瀺ããŠããŸããã
ãããã£ãŠããã¹ãèªäœã¯äžèœè¬ã§ã¯ãããŸããããã¹ãã¯æ£ããèšè¿°ãããŠããå¿
èŠããããããããªããšãçè§£ããåé¡ãåŒãèµ·ããå¯èœæ§ã®ããå Žæãæ£ç¢ºã«ãã¹ãããå¿
èŠããããŸãã
ã³ãŒãã¯
githubã§å
¥æã§ããŸã