使用Yeoman和Mocha进行NodeJS和客户端的全面集成testing

我有很好的与Yeoman一起运行的客户端testing。 Yeoman编译我的CoffeeScript,在服务器上打开testing页面,使用PhantomJS访问它,并将所有testing结果传递到命令行。 这个过程相当不好,testing结果通过alert()消息传递给Phantom进程,Phantom进程创build一个临时文件,并将消息填充为JSON。 Yeoman(well,Grunt)遍历临时文件,parsingtesting并将其显示在命令行中。

我解释过程的原因是我想添加一些东西。 我也有服务器端testing。 他们使用mocha和supertest检查API端点和Redis客户端,以确保数据库状态符合预期。 但我想合并这两个testing套件!

我不想为服务器调用写客户端模拟响应。 我不想发送服务器模拟数据。 一路上我会换服务器或客户端,testing不会失败。 我想做一个真正的集成testing。 因此,无论何时在客户端testing完成,我想要一个钩子在服务器端运行相关的testing(检查数据库状态,会话状态,移动到不同的testing页面)。

有没有解决办法? 或者说,从哪里开始对Yeoman / Grunt / grunt-mocha进行黑客攻击?

我觉得grunt-mocha里的Phantom Handlers是一个很好的开始:

 // Handle methods passed from PhantomJS, including Mocha hooks. var phantomHandlers = { // Mocha hooks. suiteStart: function(name) { unfinished[name] = true; currentModule = name; }, suiteDone: function(name, failed, passed, total) { delete unfinished[name]; }, testStart: function(name) { currentTest = (currentModule ? currentModule + ' - ' : '') + name; verbose.write(currentTest + '...'); }, testFail: function(name, result) { result.testName = currentTest; failedAssertions.push(result); }, testDone: function(title, state) { // Log errors if necessary, otherwise success. if (state == 'failed') { // list assertions if (option('verbose')) { log.error(); logFailedAssertions(); } else { log.write('F'.red); } } else { verbose.ok().or.write('.'); } }, done: function(failed, passed, total, duration) { var nDuration = parseFloat(duration) || 0; status.failed += failed; status.passed += passed; status.total += total; status.duration += Math.round(nDuration*100)/100; // Print assertion errors here, if verbose mode is disabled. if (!option('verbose')) { if (failed > 0) { log.writeln(); logFailedAssertions(); } else { log.ok(); } } }, // Error handlers. done_fail: function(url) { verbose.write('Running PhantomJS...').or.write('...'); log.error(); grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90); }, done_timeout: function() { log.writeln(); grunt.warn('PhantomJS timed out, possibly due to a missing Mocha run() call.', 90); }, // console.log pass-through. // console: console.log.bind(console), // Debugging messages. debug: log.debug.bind(log, 'phantomjs') }; 

谢谢! 这将有一个赏金。

我不知道约 – 我还没有尝试过 – 但我得到了其余的拼图运行。 我相信你会弄清楚其余的。

为什么要进行集成testing?

在你的问题中,当你同时运行客户端testing和服务器端testing时,你正在谈论这种情况。 我假设由于某种原因,你不能同时运行两个testing集相同的模拟。 否则,如果你在客户端改变了模拟,你的服务器端testing会失败,因为他们会得到破解的模拟数据。

你需要的是集成testing,所以当你在无头浏览器中运行一些客户端代码时,你的服务器端代码也会运行。 而且,仅仅运行你的服务器端和客户端代码是不够的,你也希望能够把双方的断言,不是吗?

集成testing与节点和PhantomJS

我在网上find的大多数集成testing的例子都是使用Selenium或者Zombie.js 。 前者是推动真实浏览器的基于Java的大型框架,后者则是围绕jsdom的简单封装。 我假设你对这两者中的任何一个都犹豫不决,宁愿使用PhantomJS 。 棘手的部分当然是从Node应用程序中运行。 我就是这样。

有两个节点模块可以驱动PhantomJS:

  1. 幻影
  2. 节点幻象

不幸的是,这两个项目似乎都被他们的作者放弃了,而其他社区成员则将其分开,并适应他们的需求 这意味着这两个项目都分叉了很多次,所有的货叉都没有运行。 API几乎不存在。 我用一把幻影叉子进行了testing(谢谢Seb Vincent )。 这是一个简单的应用程序:

 'use strict'; var express = require('express'); var app = express(); app.APP = {}; // we'll use it to check the state of the server in our tests app.configure(function () { app.use(express.static(__dirname + '/public')); }); app.get('/user/:name', function (req, res) { var data = app.APP.data = { name: req.params.name, secret: req.query.secret }; res.send(data); }); module.exports = app; app.listen(3000); })(); 

它侦听/user请求并返回path参数name和查询参数secret 。 这里是我打电话给服务器的页面:

 window.APP = {}; (function () { 'use strict'; var name = 'Alex', secret ='Secret'; var xhr = new XMLHttpRequest(); xhr.open('get', '/user/' + name + '?secret=' + secret); xhr.onload = function (e) { APP.result = JSON.parse(xhr.responseText); }; xhr.send(); })(); 

这是一个简单的testing:

 describe('Simple user lookup', function () { 'use strict'; var browser, server; before(function (done) { // get our browser and server up and running phantom.create(function (ph) { ph.createPage(function (tab) { browser = tab; server = require('../app'); server.listen(3000, function () { done(); }); }); }); }); it('should return data back', function (done) { browser.open('http://localhost:3000/app.html', function (status) { setTimeout(function () { browser.evaluate(function inBrowser() { // this will be executed on a client-side return window.APP.result; }, function fromBrowser(result) { // server-side asserts expect(server.APP.data.name).to.equal('Alex'); expect(server.APP.data.secret).to.equal('Secret'); // client-side asserts expect(result.name).to.equal('Alex'); expect(result.secret).to.equal('Secret'); done(); }); }, 1000); // give time for xhr to run }); }); }); 

正如你所看到的,我必须在超时时间内轮询服务器。 这是因为所有的幻像绑定是不完整的,太有限制了。 正如你所看到的,我可以在单个testing中检查客户端状态和服务器状态。

用Mocha运行你的testing: mocha -t 2s你可能需要增加默认的超时设置,让更多的进化testing运行。

所以,你可以看到整个事情是可行的。 这里是完整的例子回购。