Ruby on Rails fixturesとfactory_girl_rails

Ruby on Railsのテストにfixturesだけでは限界を感じたので、factory_girl_railsを導入してみた。

使用準備

Ruby on Railsプロジェクトを作成

>rails new sample_factory_girl_rails
>cd sample_factory_girl_rails

 

factory_girl_railsの使用準備

Gemfileにfactory_girl_railsの定義を加える

 

>bundle install

 

モデルを作成

>rails g model post title contributer body
      invoke  active_record
      create    db/migrate/20130101223041_create_posts.rb
      create    app/models/post.rb
      invoke    test_unit
      create      test/unit/post_test.rb
      invoke      factory_girl
      create        test/factories/posts.rb

Gemfileでfactory_girlを使用するようにすると、以降のモデル作成時に、test/fixtures/モデル名複数系.ymlではなく、test/factories/モデル名複数系.rbが作成される。

今回はpostモデルを作成したためtest/factories/posts.rbが作成された。

 

test/factories/posts.rbのデフォルトの内容

 

factory_girl_railsのREADME.mdには、ファクトリを自動作成するには

の設定が必要と記載してあるが、設定無くてもファクトリファイルが作成される。

 

ユニットテストから利用してみる

まずはデータベースを作成

>rake db:migrate

 

テストからFactoryGirlが使えるか確認するために、post_post.rbを書き換えてみる。

 

テスト実行結果

>rake test:units
Run options:

# Running tests:

********************
0
#<Post id: 1, title: "MyString", contributer: "MyString", body: "MyString", created_at: "2013-0
1-01 23:09:36", updated_at: "2013-01-01 23:09:36">
1
********************
.

Finished tests in 3.306189s, 0.3025 tests/s, 0.3025 assertions/s.

1 tests, 1 assertions, 0 failures, 0 errors, 0 skips

 

FactoryGirl、ちゃんと使えてるね!

fixturesとFactoryGirlを併用する

FactoryGirlはデータを動的に作成するという点で便利だけど、やっぱりfixturesの静的な定義も捨てがたい。

とか

unit testはFactoryGirlで十分だけど、functional testのデータはfixturesで作成したい

とか。

 

こういった場合でも、特に何も設定とかせずに、test/fixtures/posts.ymlファイルを作成するだけで、fixturesとFactoryGirlを併用することができる。

 

と、いうことで、test/fixtures/posts.ymlを作成する。

posts.ymlを作成すると、テストの実行前に、fixturesをちゃんとロードしてくれる。

 

確認のため、post_test.rbに1行加える。

 

もう一度ユニットテストを実行してみる。

>rake test:units
Run options:

# Running tests:

********************
1
#<Post id: 980190962, title: "title from fixture", contributer: "contributer from fixture", bod
y: "body from fixture", created_at: "2013-01-02 00:41:54", updated_at: "2013-01-02 00:41:54">
#<Post id: 980190963, title: "MyString", contributer: "MyString", body: "MyString", created_at:
 "2013-01-02 00:41:54", updated_at: "2013-01-02 00:41:54">
2
********************
.

Finished tests in 3.254186s, 0.3073 tests/s, 0.3073 assertions/s.

1 tests, 1 assertions, 0 failures, 0 errors, 0 skips

 

fixturesを作成していない場合はPost.countは0件だったのに対して、fixturesを作成すると、Post.countは1件になっている。

FactoryGirlがfixturesより優れているというわけではない

fixtureとFactoryGirl、それぞれメリットとデメリット、得意と不得意があると思う。

 

例えば、fixtureで定義するYAML形式のデータは、テストが肥大化していくとメンテナンスコストが増える反面、データそのものをズバリ記述するので間違いが入り込みにくい。

 

逆にFactoryGirlのファクトリ定義は、メンテナンスコストは楽だがデータ定義がプログラムなので、間違いが入り込みやすい。

 

テスト駆動であるにしても、テストというものは分かりやすく間違いが入り込みにくくなければならないから、この点を尊重するならfixturesを選択するか、FactoryGirlの基本的で間違いが入り込みにくい範囲のみを使用するに留めるべきだと思う。

(FactoryGirlのbeforeやafterを使い始めると、今度はテストデータの生成それ自体を検証したくなる。)

FactoryGirlはユーザアカウントモデルのテストに便利

私がFactoryGirlを使おうと思うきっかけになったのは、deviseでユーザアカウント用のモデルを作成したときに、encrypted_passwordをfixtureとして定義しようとしたときに、暗号化した文字列をfixtureファイルに定義しなければならない点が気に入らなかったから。

 

その点、FactoryGirlなら、暗号化する前のパスワードをテストデータとして定義できる。

fixtureとして定義されたデータは直接データベースにロードされるのに対して、FactoryGirlとして定義されたファクトリは、いったんモデルの登録処理を経るため、暗号化する前のパスワードを定義できる。

コメントを残す

トラックバック: http://pgnote.net/wp-trackback.php?p=1483