7

私は現在、ember.js に基づくアプリケーションのテストスイートを travis-ci に統合する方法を研究しています。まず第一に、私たちはオープンソース サービスを利用しておらず、プライベート リポジトリなどに使用しています。

いくつかのオープンソース プロジェクトがどのように ember.js テスト スイートを実行しているかを調べたところ、彼らは、誰かがリポジトリにプッシュするたびにおそらく更新されるプロジェクトでサーバーをセットアップしているようです。次に、PhantomJSを使用してそのサーバーでテストを実行します (実際には travis-ci 自体ではありません)。

このアプローチで私が抱えている問題は、別のステップ (そして最終的には複雑さ) が追加されることです。PhantomJS を使用してテスト スイートを実行できるように、サーバーを最新のコードで更新および維持する必要があります。

もう 1 つの欠点は、PR (プル リクエスト) をテストする方法が分からないことです。サーバーは、PR からのコードで更新する必要があります。PR をマージする前にテストすることは、travis-ci の優れた点の 1 つです。

CLI を介してのみ ember.js テストを実行することについては、何も見つけることができませんでした。誰かがこの問題に私の前に取り組んでくれることを願っています。

4

1 に答える 1

5

travis-ci に関するご質問にはお答えできませんが、jasmine を使用した ember.js コードの単体テストについて、いくつかの考えを提供できます。

ember.js を使い始める前に、jasmine と jasmine-node という単純な node.js モジュールを使って単体テストを行っていました。これにより、ブラウザを開いたり、「js-test runner」などをハックしたりすることなく、コマンドラインからジャスミン単体テストのスイートをすばやく実行できました。

ジャスミン、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 アプリを使用してテスト結果のページがスクレイピングされます。

他の人がどのように動作するかをすぐに確認できるように、2 つの異なる例を github プロジェクトに入れることに時間を費やしました。これは独断的であるため、プラグインがテストを実行するために使用するプロジェクト ルートに html ファイルが必要になります。また、最近の jQuery とともに jasmine と jasmine-html も必要です。

個人的にはこの問題を解決し、単純なジャスミンを使用して ember に対するテストを作成し、ブラウザーなしでコマンドラインから実行できるようになりました。

これは、このテスト ランナーを使用して最近、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', '');
  });
});

これは、私が上記で単体テストを行っている本番のemberビューです

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 に答える