CI与emberjs

Til*_*ill 7 testing continuous-integration integration-testing travis-ci ember.js

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

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

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

另一个缺点是我没有看到它如何使我们能够测试PR(拉取请求).必须使用来自PR的代码更新服务器.在合并之前测试PR是travis-ci的优点之一.

我找不到很多/关于只通过CLI运行ember.js测试的事情 - 我希望有人在我面前解决这个问题.

Tor*_*ups 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运行器并使用非常基本的快速Web应用程序擦除页面以获得测试结果.

我花时间在github项目中放了两个不同的例子,以便其他人可以看到它如何快速工作.这是固执己见,因此您需要在项目根目录中使用html文件,插件将使用该文件来执行测试.它还需要jasmine,jasmine-html以及最近的jQuery.

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

这是一个茉莉花单元测试样本,我最近在这个测试运行时加入了一个ember视图.如果您想了解在应用程序中如何使用测试中的视图,这里是完整的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', '');
  });
});
Run Code Online (Sandbox Code Playgroud)

这是我在上面进行单元测试的生产余烬视图

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', '');
    }
  }
});
Run Code Online (Sandbox Code Playgroud)