はじめに
安定的なテスト環境を構築するための第一ステップとして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](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F74580%2F20ca8de8-19c0-9252-f944-ca2d83e20afa.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=92734057145c30cf5fec64c9fcba5c30)
ここからわかるように今回4つのモデルがあったが実質は3つでよい。
絶対作らなければならないオブジェクトは UserとClient、もうひとつJobOffer(JobApplyでも可)である。JobApply(JobOffer)に関しては他の3つから作れる。
ポイントとしては最小単位をFactoryGirlを使用して生成するということ。
既存のサービスにおいてバリデーションなどが複雑だったりして作りにくかったりもするのでこういった対応方法にすると意外とすんなりバリデーションもクリアできます。
実際に書いてみる
JobApply Modelに関して
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については以下です。
FactoryGirl.define do
factory :user do
last_name "HOGE"
first_name "太郎"
last_kana "ほげ"
first_kana "タロウ"
birthday "2015-12-08"
end
end
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
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