はじめに
emberはフロントエンドフレームワークですが、そのままで使うよりember-cliというコマンドラインツールでrailsの様に開発するのがベストな方法と言えます。
ember-cliの利点
- es6で書ける
- 命名規約があるのでファイル名が統一される
- その他のフロントエンド開発のようにnpmとかbowerの資産を使えるビルドシステムが備わっている
- ユニットテストが書きやすい
等があります。
僕はこの中ではテストが書きやすいというのが大きいと思います。
どうしてもフロントエンドのユニットテストというとmodelばかりでviewに近くなるとcapybara等でインテグレーションテストになることが多いと思いますが、やはりユニットテストがかけると開発のモチベーションやメンテナンス性が違うと思うからです。
ember-railsの利点
しかしながら、ember-cliはフロントエンド単体の開発には適していますがrailsを使った既存のwebアプリに組み込むとなると、追加でフロント用のサーバーを立てたり、API認証の仕組みを入れたり、いろいろ面倒です。
そんな時に便利なのがember-railsです。
- ember:bootstrap等のジェネレーターがある(componentやmodel用のもあります)
- railsのエコシステムに乗れるので今までのjavascriptの扱いとさほど変わらない
等が利点だと思います。
これでrailsのフロントエンド開発にemberを簡単に使えるんですが、特に公式のREADMEにはテストについては言及されていないです。
ember-cliでは手厚くテストがサポートされている感じなのに、rails環境で出来ないなんてもったいないので調べてみました。
ember-mocha
まずはテストフレームワークについて、公式のフレームワークとしてはember-qunitが推奨されていますがember-mochaを使うという選択肢もあります。
railsのテストではrspecを使っているので似たような感じで書けるmochaが使えると嬉しいところです。
ということでember-mochaを使うことにしました。
しかし、ember-qunitでも同じように導入できると思います。
railsで使うためにはrails-assetsを利用します
+ source "https://rails-assets.org"
group :development, :test do
+ gem 'rails-assets-ember-mocha'
end
Teaspoon
Teaspoonはrailsのjavascriptユニットテストにとても便利なgemです。
始め方も簡単で以下のようにすれば環境が整います。
group :development, :test do
gem 'rails-assets-ember-mocha'
+ gem 'teaspoon'
end
$ bundle install
$ bin/rails generate teaspoon:install --framework=mocha --coffee
これで必要なディレクトリとファイルが揃いまいした。
spec/javascripts/spec_helper.coffee
正直環境を作ると言ってもここのファイルにちょこっとコードを書き足すだけです
デフォルトのコメントが長いので省略していますが以下のようにすればokです
# require support/expect
# require support/sinon
#= require support/chai
# require support/your-support-file
#
#= require application
#= require ember-mocha/ember-mocha
window.expect = chai.expect
window.setupApplication = ->
setResolver(Ember.DefaultResolver.create(namespace: App))
setupApplication()
App.setupForTesting()
Componentのテスト
App.XHogeComponentというcomponentがある場合は
spec/javascripts/components/x-hoge_spec.coffee というファイルを作成して以下のように書きます
# templateはこのようになっているとする
<span>{{item.name}}</span>
describeComponent 'x-hoge', 'XHogeComponent', {
needs: ['template:components/x-hoge']
}, ->
beforeEach ->
@item = Ember.Object.create(name: 'sample name')
@component = @subject()
Ember.run =>
@component.set('item', @item)
@component.appendTo('#ember-testing')
afterEach ->
@component.destroy()
it 'is exists', ->
expect(@$().text()).to.equal('sample name')
@subject()という関数の戻り値で対象のcomponentのインスタンスが返ってきますのであとはpropertyをsetする等はEmber.run()の中にクロージャを渡して実行させます。
viewのテストが公式ドキュメントに載っていないのはなぜだろう?と悩んでいたのですが、viewは基本使わずにcomponentのみで実装する方がいいみたいですね
参考:https://speakerdeck.com/tomdale/ember-2-dot-0-in-practice?slide=27
複数のApplicationがある場合
複数のEmber.Applicationを作成している場合はsetupApplication
にあたるものを複数作成しておいて各テストファイルのbeforeSetup
の中で呼び出すようにします
window.setupHoge = ->
setResolver(Ember.DefaultResolver.create(namespace: Hoge))
window.setupFuga = ->
setResolver(Ember.DefaultResolver.create(namespace: Fuga))
Hoge.XHogeComponentのテストの場合
describeComponent 'x-hoge', 'XHogeComponent', {
needs: ['template:hoge/components/x-hoge'],
beforeSetup: -> setupHoge()
}, ->
beforeEach ->
@component = @subject()
it 'is exists', ->
expect(@component).to.be.ok
Teaspoonでテストを走らせる
localhost:3000/teaspoonにアクセスすると通常のブラウザで実行できるようですが、CIする場合のコマンドはこちらです
$ RAILS_ENV=test bin/rake teaspoon
RAILS_ENV=testを指定しておかないとdevelopmentで動作するので注意が必要です。
まとめ
テストもきっちり書けるemberがよく出来ているので素材を組み合わせるだけですが、Backbone.js等で辛くなりがちがユニットテストが書けるのはいいですね。