7

我目前正在研究将基于 ember.js 的应用程序的测试套件集成到 travis-ci 中的方法。所以首先,我们不在开源服务上,我们将它用于私人存储库等。

我查看了几个开源项目如何运行他们的 ember.js 测试套件,看起来他们用他们的项目设置了一个服务器,每当有人推送到存储库时,它可能会更新。然后 PhantomJS用于在该服务器上运行测试(实际上不在 travis-ci 本身上)。

我对这种方法的问题是,这增加了另一个步骤(并最终增加了复杂性):我必须使用最新代码更新和维护服务器,以便我可以使用 PhantomJS 来运行测试套件。

另一个缺点是我看不到它如何使我们能够测试 PR(拉请求)。服务器必须使用 PR 中的代码进行更新。在合并之前测试 PR 是 travis-ci 的一大优点。

我找不到太多/任何关于仅通过 CLI 运行 ember.js 测试的信息——我希望有人在我之前解决了这个问题。

4

1 回答 1

5

我无法回答你关于 travis-ci 的问题……但我可以提供一些关于使用 jasmine 对 ember.js 代码进行单元测试的想法。

在我开始使用 ember.js 之前,我正在使用 jasmine 和一个名为 jasmine-node 的简单 node.js 模块进行单元测试。这使我可以从命令行快速运行一套 jasmine 单元测试,而无需打开浏览器或使用“js-test runner”/等进行破解

当我使用 jasmine、jquery 和简单的 javascript 模块来保持我的 javascript 代码人类可读时,这非常有用。但是当我需要使用 ember/handlebars/etc 时,jasmine-node 模块就崩溃了,因为它希望你在全局和窗口上都有所有可用的东西。但是因为 ember 只是一个浏览器库,并不是所有东西都在“全局”上

我开始研究 PhantomJS 并且像您自己一样看不到自己增加了复杂性。因此,我决定花一个周末来写下 jasmine 测试运行器空间中缺少的东西,而不是围绕这个问题进行破解。我想要 jasmine-node 的相同功能(这意味着我的 CI 盒子上只需要一个最新版本的 node.js 和一个简单的 npm 模块来运行测试)

我编写了一个名为jasmine-phantom-node的 npm 模块,其核心是使用 node.js 来运行 phantomJS =>,这反过来会启动一个常规的 jasmine html 运行程序,并使用一个非常基本的 express web 应用程序抓取页面以获取测试结果。

我花时间在 github 项目中放置了 2 个不同的示例,以便其他人可以快速了解它是如何工作的。这是自以为是的,因此您需要在项目根目录中创建一个 html 文件,插件将使用该文件来执行您的测试。它还需要 jasmine 和 jasmine-html 以及最近的 jQuery。

它为我个人解决了这个问题,现在我可以使用简单的 jasmine 编写针对 ember 的测试,并在没有浏览器的情况下从 cmd 行运行它。

这是我最近在使用这个测试运行器时针对 ember 视图编写的示例 jasmine 单元测试。如果您想查看被测视图如何在应用程序中使用,这里是完整的 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', '');
    }
  }
});
于 2012-09-24T02:54:26.777 回答