我目前正在研究如何将基于ember.js的应用程序的测试套件集成到travis-ci中。首先,我们不是在开源服务上,而是将它用于私有存储库等。
我看了几个开源项目如何运行他们的ember.js测试套件,看起来他们设置了一个服务器,他们的项目可能会在有人推送到存储库时更新。 Then PhantomJS用于在该服务器上运行测试(实际上不在travis-ci本身上)。
我使用这种方法的问题是,这增加了另一个步骤(并最终增加了复杂性):我必须使用最新代码更新和维护服务器,以便我可以使用PhantomJS来运行测试套件。
另一个缺点是我没有看到它如何使我们能够测试PR(拉取请求)。必须使用来自PR的代码更新服务器。在PR合并之前测试PR是travis-ci的优点之一。
我无法找到关于仅通过CLI运行ember.js测试的任何内容 - 我希望有人在我面前解决这个问题。
答案 0 :(得分:5)
我不能谈谈你关于travis-ci的问题......但是我可以提供一些关于使用jasmine对ember.js代码进行单元测试的想法。
在我开始使用ember.js之前,我使用jasmine和一个名为jasmine-node的简单node.js模块进行单元测试。这使我能够从命令行快速运行一套茉莉花单元测试,而无需打开浏览器或破解“js-test runner”/ etc
当我使用jasmine,jquery和简单的javascript模块时,我的工作很棒,我曾经保持我的javascript代码是人类可读的。但是当我需要使用ember / handlebars / etc时,茉莉花节点模块就掉了下来,因为它希望你在全局和窗口都有可用的东西。但是因为ember只是一个浏览器库而不是一切都在“全球”
我开始关注PhantomJS,就像你自己看不到自己增加复杂性一样。所以我决定周末去写茉莉花测试跑者空间里缺少的东西,而不是乱砍。我想要与jasmine-node相同的功能(意味着我在CI盒子上需要的只是最新版本的node.js和一个简单的npm模块来运行测试)
我写了一个名为jasmine-phantom-node的npm模块,其核心是使用node.js来运行phantomJS =>反过来,它会激活一个常规的jasmine html跑步者,并使用一个非常基本的快速网络应用程序来搜索测试结果的页面。
我花时间在github项目中放置了两个不同的示例,以便其他人可以看到它如何快速工作。这是固执己见,因此您需要在项目根目录中使用html文件,插件将使用该文件来执行测试。它还需要jasmine,jasmine-html以及最近的jQuery。
它为我个人解决了这个问题,现在我可以使用简单的jasmine编写针对ember的测试,并在没有浏览器的情况下从cmd行运行它。
这是一个茉莉花单元测试样本,我最近在这个测试运行时加入了一个ember视图。 Here是完整的ember / django项目的链接,如果你想看看应用程序中如何使用测试中的视图。
require('static/script/vendor/filtersortpage.js');
require('static/script/app/person.js');
describe ("PersonApp.PersonView Tests", function(){
var sut, router, controller;
beforeEach(function(){
sut = PersonApp.PersonView.create();
router = new Object({send:function(){}});
controller = PersonApp.PersonController.create({});
controller.set("target", router);
sut.set("controller", controller);
});
it ("does not invoke send on router when username does not exist", function(){
var event = {'context': {'username':'', 'set': function(){}}};
var sendSpy = spyOn(router, 'send');
sut.addPerson(event);
expect(sendSpy).not.toHaveBeenCalledWith('addPerson', jasmine.any(String));
});
it ("invokes send on router with username when exists", function(){
var event = {'context': {'username':'foo', 'set': function(){}}};
var sendSpy = spyOn(router, 'send');
sut.addPerson(event);
expect(sendSpy).toHaveBeenCalledWith('addPerson', 'foo');
});
it ("does not invoke set context when username does not exist", function(){
var event = {'context': {'username':'', 'set': function(){}}};
var setSpy = spyOn(event.context, 'set');
sut.addPerson(event);
expect(setSpy).not.toHaveBeenCalledWith('username', jasmine.any(String));
});
it ("invokes set context to empty string when username exists", function(){
var event = {'context': {'username':'foo', 'set': function(){}}};
var setSpy = spyOn(event.context, 'set');
sut.addPerson(event);
expect(setSpy).toHaveBeenCalledWith('username', '');
});
});
以下是我在上面进行单元测试的生产余烬视图
PersonApp.PersonView = Ember.View.extend({
templateName: 'person',
addPerson: function(event) {
var username = event.context.username;
if (username) {
this.get('controller.target').send('addPerson', username);
event.context.set('username', '');
}
}
});