LoginSignup
18
17

More than 5 years have passed since last update.

FactoryGirlを超初心者が書くときの注意点

Last updated at Posted at 2015-12-08

はじめに

安定的なテスト環境を構築するための第一ステップとしてFactoryGirlを導入して書いてみたが、書いていくうちにごちゃごちゃになっていってしまった。今、また最初からやり直すならこうやるのだろうなと思うことがあったのでメモとして残しておこうと思います。

よく使うもの

「create」 whereなどDBからデータを取得したいときに使用する
FactoryGirl.create(:users)

「build」 DBには保存されないのでバリデーションのテストのときに使用したりする
FactoryGirl.build(:users)

「sequence」 連番を使って重複しないデータがほしいときに使用する

sequence :mail do |n|
  "person#{n}@example.com"
end

「trait」 引数のオプションを付けるイメージで任意のコードを実行させたいときに使用する

trait :with_mail do
  mail "hogehoge@hoge.co.jp"
end

「associations」 多:多 や 多:1 などを表したいときに使用するbelongs_toのイメージ
association :mail
ちなみにfactoryの名前とbelong_toの名前が一緒のときはmailと書いておくだけでよい!またhas_manyのときは

after(:create) do |user|
  user.user_hobies{[FactoryGirl.build(:hoby)]}
end

のようにして対応したりできます。

「参考URL」
http://tech.grooves.com/entry/2015/04/28/173025
http://qiita.com/muran001/items/436fd07eba1db18ed622

実用例

就職支援サイトの運用時を例に書いてみる。
最初にどういうモデルがあるか。。。
今回は

ユーザー  クライアント
user     client
         job_offer
         job_apply

みたいのを想定してみる。ここで結構重要になると思っているのが各々の関係性である。冒頭で「やり直すなら・・」と思っていたのがこの部分です笑。手当たりしだいで進めていった結果「こう作っていればよかった」みたいなことに後々なってしまいましたので。。

大まかにモデルの関係性は以下のようになると思います。

・企業は求人をいくつも出している。
・ユーザーはその求人に対して応募をいくつも出せる。
・1つの求人に対しては応募は一回まで

スクリーンショット 2015-12-08 21.31.08.png

ここからわかるように今回4つのモデルがあったが実質は3つでよい。
絶対作らなければならないオブジェクトは UserとClient、もうひとつJobOffer(JobApplyでも可)である。JobApply(JobOffer)に関しては他の3つから作れる。

ポイントとしては最小単位をFactoryGirlを使用して生成するということ。
既存のサービスにおいてバリデーションなどが複雑だったりして作りにくかったりもするのでこういった対応方法にすると意外とすんなりバリデーションもクリアできます。

実際に書いてみる

JobApply Modelに関して

spec/models/job_apply_spec.rb
describe JobApply do
  context "1.設定したuser/clientでjob_applyが生成できる" do
    example "1.1.1 設定したuser/clientでデータが生成できる" do
      user = FactoryGirl.create(:user)
      job_offer = FactoryGirl.create(:job_offer)
      job_apply = JobApply.create(user_id: user.id, job_offer_id: job_offer.id)
      expect(job_apply).to be_true
    end
  end
end

みたいにjob_applyは表現できます。specはここでは触れないのでおいておきます。FactoryGirlについては以下です。

spec/factories/users.rb
FactoryGirl.define do
  factory :user do
    last_name "HOGE"
    first_name "太郎"
    last_kana "ほげ"
    first_kana "タロウ"
    birthday "2015-12-08"
  end
end

spec/factories/clients.rb
FactoryGirl.define do
  factory :client do
    name HOGE

    trait :with_job_offer do
      after(:create) do |client|
        3.times { FactoryGirl.create(:job_offer, client: client) }
      end
    end

  end
end

spec/factories/job_offers.rb
FactoryGirl.define do
  factory : job_offer do
    sequence(:title) {|n|"テスト#{n}"}

    client #associationをかかなくてもいける
  end
end

まとめ

実際にコードとかを書いてみましたが伝えにくいですねw
テストコードに限ったことではないのですが、僕が大事なんだろうなと思ったのは
図を用いましたが、関係性/設計のところではないかと思いました。
この「関係性を明らかにし、それこそhas_many belongs_toをtrait :with_job_offerで書いてjob_offerのほうではassociationを書く。」を最初におさえて徹底することがコードを書いていく中で後々変なことになることのリスクを最小限にできる方法ではないかと思うので
初めてやる人はおさえておくとよいかもしれません。

以下を見ると比較的簡単に手がつけられると思います。
http://shim0mura.hatenadiary.jp/entry/2014/06/29/002102
http://blog.livedoor.jp/sasata299/archives/51931175.html

18
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
17