2009-12-22 [長年日記]

[test] fixture replacement 決定戦

まとめ中

人気健全書式名前動的分類機能上書汎用合計
FactoryGirl××8pt
Machinist7pt
ObjectDaddy×××-3pt

めも

  • FGはdefineの仮引数周りが無駄 (blueprintで改善)
  • FGはinstanceをフラットに管理しすぎ
  • FGのsequence(next)はイケてる
  • FGはAR前提
  • Machinistは定義がイケてるが、名前がダサイ(make_unsaved)
  • Machinistはメソッド名が衝突しそう(makeはアカン)
  • Machinistはinstanceをクラス毎に分類できるが、Shamレベルまで落ちるとフラットになる片手落ち感
  • Daddyの使えなさは異常
  • FGの継承はどうやるの?(-> :parent)
  • FG.blueprint は :parent を理解してくれない

試行錯誤

  • とりあえず使ってみるべ。まずは FactoryGirl

FactoryGirl

Factory.sequence :login do |i|
  "login#{i}"
end

Factory.define(:user) do |user|
  user.login   {Factory.next(:login)}
  user.name    '(名称未設定)'
  user.email   {|u| "%s@example.com" % u.login}
  user.password 'generic'
  user.password_confirmation 'generic'
end
  • Syntaxが辛い。:user(クラス名), user(ブロック引数), user(receiver)の冗長性とか無理
    • blankslate でやった方がいいですよね
  • てか、Rubyがbundleで持っているべき
    • 1.9にはBasicObjectがありますよ
  • 世の中はまだ1.8だし
    • 構造が違うから直接1.8にバックポートするのは無理デスネ
  • 1.8に適当なblankslate.rbをバックポート希望
    • 閑話休題。この書式に耐えかねた先人(notahat)がMachinistを作成していますよ
  • おし、それに乗っかろう

Machinist

User.blueprint do
  login   'login'
  name    '(名称未設定)'
  email   {"%s@example.com" % login}
  password 'generic'  password_confirmation 'generic'
end
  • うがっ、すっきり!DSL 的で可読性が高い。これだよこれ!
    • でも、FGにあったsequence機能はありませんが...
  • そこはブロックだから、なんくるないさー。てか、「blueprint」てどういう意味?
    • 文字通り「青写真」ですね。スケルトン(テンプレート)定義ぐらいの意味でよろしいかと
  • Userのテンプレート定義で「User.blueprint」。簡潔だね。Machinist最高!!
    • でもまぁ、blueprint書式ならFGにもありますけどね
  • mjd!?

FactoryGirl + blueprint syntax

require "factory_girl/syntax/blueprint"
Factory.sequence :login do |i|
  "login#{i}"
end

User.blueprint do
  login   {Factory.next(:login)}
  name    '(名称未設定)'
  email   {|u| "%s@example.com" % u.login}
  password 'generic'
  password_confirmation 'generic'
end
  • おいおいFactoryGirlって完璧じゃねーか
    • 完璧スレの住人乙
  • さっそく :admin を追加しよう。FGで差分ってどう書くの?
    • つ :parent

FactoryGirl で継承

Factory.define(:admin, :parent=>:user) do |u|
  u.name '管理者'
end
  • って、ダサイ書き方に戻っちゃったよ。もしかして?
    • はい。blueprint 書式だと継承は書けません。すいません
  • ちょw。そもそも:parentなんてキーワードも来週にはもう忘れてるし
    • 後発の Machinist ではどうなってるんでしょう?

Machinist で継承

User.blueprint(:admin) do
  name '管理者'
end
  • 素晴らしい!記述が直感的でエレガントだ
    • ふふふ
  • Pete が必死に「FG は Syntax がダサイ!」とdisってた意味がわかったよ
    • ありがとうございます
  • そう言えば、Syntax だけでなくて Philosophy も dis ってたよね?あれはどういう意味?
    • あぁ、FGはinstanceをflatに管理してるんですよ
  • どういうこと?
    • 今、:admin を追加しましたよね。これが global に :admin として登録されちゃうんですよ
  • なるほど、次に別クラスで:adminという名前を登録しようとしても競合するのか
    • はい。仕方なく :user_admin, :role_admin みたいな名前空間を考慮して登録して行く事になります
  • 確かに、:admin はないとしても、:dummy とかすぐぶつかりそう

FactoryGirl

Factory.define(:user_dummy, :parent=>:user) do
  ...
end
Factory.define(:role_dummy, :parent=>:role) do
  ...
end

user = Factory(:user_dummy)
role = Factory(:role_dummy)
  • ダサイね。「Module 無き Ruby の世界」みたいな。考えただけで地獄ぽ
    • そこで、Machinistではクラス毎に名前空間を持って管理してます

FactoryGirl

User.blueprint do
  name '舞波'
end
User.blueprint(:dummy) do
  name 'ダミーデータ'
end
Item.blueprint do
  name '商品'
end
Item.blueprint(:dummy) do
  name 'ダミー商品'
end

User.plan           # => {'name' => '舞波'}
User.plan(:dummy)   # => {'name' => 'ダミーデータ'}
Item.plan           # => {'name' => '商品'}
Item.plan(:dummy)   # => {'name' => 'ダミー商品'}
  • おいおいMachinsitって完璧じゃねーか
    • DD乙
  • てか、plan て何ですの?
    • hashとして返すメソッドです。FGと同様に用途に応じて3種類のメソッドを用意しています

FactoryGirlとMachinistのメソッド比較

戻り値FactoryGirlMachinist
saved instanceFactory.create(:user)User.make
unsaved instanceFactory.build(:user)User.make_unsaved
HashFactory.attributes_for(:user)User.plan

  • Machinistはシンプルで直感的だけど、クラスメソッドの汚染がやだな
    • あぁ、あぅ、ふgぁ、それ言われたらヤバイな、って思ってたんですよ(ふがふが
  • しかも一番使いそうな unsaved の名前が無駄に長い
    • スイマセン。そこも4文字でいいのがあればよかったんですが
  • いいよ。許す。この3つのメソッドは封印するよ。FGのよりも User.make の方が可読性高いし!
    • 言い辛いんですが、FGにもそういう機能ありますけど...
  • mjd!?

FactoryGirl + generate

require 'factory_girl/syntax/generate'

# same as Factory.build(:user)
User.generate

FactoryGirlのgenerate書式

メソッド内容ARで言うとFactoryで言うと
generateインスタンスを保存して返すcreateFactory.build (and save)
generate!generateして失敗時に例外を出すcreate!Factory.create
spawnインスタンスを作成して返すnewFactory.build

  • 凄いけど名前混乱する。Factoryにそのまま委譲すればいいのに

(以下、鋭意妄想中)

参考


サイト内検索 (by Google)

| JRuby | Rails | Berryz | ℃-ute | エッグ | jQuery |

過去

2009年
12月
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

未来

コンタクト