こんにちは、Taroです。
最近Railsを勉強し始め、やっとテストコードを書くようになりました。
FactoryGirlって便利ですよね。
最近Railsを勉強し始め、やっとテストコードを書くようになりました。
FactoryGirlって便利ですよね。
特に連番を作成する際に使用するsequenceがお気に入りです。
しかし先日愛するsequenceに頭を悩まされることになりました。
(当たり前だよ、とは言わないでください。)
しかし先日愛するsequenceに頭を悩まされることになりました。
(当たり前だよ、とは言わないでください。)
sequenceのnって、テスト2週目でも値がリセットされるわけじゃないんだぜ!
まずは状況を理解していただくため、例をあげたいと思います。
例えば下記のようにModelを定義します。
spec/factories/item.rb
例えば下記のようにModelを定義します。
spec/factories/item.rb
FactoryGirl.define do
factory :item do
sequence(:name) { |n| "sample#{n}" }
sequence(:category) { |n|
n % 4 == 0 ? 4 : n % 4
}
end
end
意図としては、名前は「sample1」、「sample2」。。。といった具合に増やします。
ただカテゴリは1〜4の中に収めようとしました。
ただカテゴリは1〜4の中に収めようとしました。
そしてテストコードを書きます。
spec/models/item_spec.rb
(ただし、1つ1つ指定できないことがネックです。)
12レコード作成しておりますが、これは意図した数です。
spec/models/item_spec.rb
require 'rails_helper'
RSpec.describe Item, type: :model do
context 'itemのレコードが存在するとき' do
before do
FactoryGirl.create_list(:mst_content_type, 12)
end
it 'テスト1' do
# 省略
end
it 'テスト2' do
# 省略
end
end
end
create_listメソッドを使うことで、第2引数の数だけサンプルレコードを作成できます。(ただし、1つ1つ指定できないことがネックです。)
12レコード作成しておりますが、これは意図した数です。
テストを実行しました。何やら狙った結果が得られません。
どうやらサンプルデータがおかしいということが分かりました。
カテゴリーで絞り込みを行っていると、この辺りで引っかかり、狙った結果を得ることができません。
また、私のように不作法なリレーションのテストもわけが分からないことになります。
(テストコードが悪いのか、それともそもそもテストしたいソースが悪いのか)
どうやらサンプルデータがおかしいということが分かりました。
# テスト1週目
id: 1 name: sample1 category: 1
id: 2 name: sample2 category: 2
...以下10個同様のものが作成された。
# テスト2週目
id: 13 name: sample13 category: 3
id: 14 name: sample14 category: 4
...以下10個同様のものが作成された。
お気づきでしょうか?1週目と2週目でレコードが違うことに。カテゴリーで絞り込みを行っていると、この辺りで引っかかり、狙った結果を得ることができません。
また、私のように不作法なリレーションのテストもわけが分からないことになります。
(テストコードが悪いのか、それともそもそもテストしたいソースが悪いのか)
いやいや、なんでお前、カテゴリーみたいな範囲のある値にsequence使ってるの?
おっしゃる通りです。。。FactoryGirlにはtraitというグループ分けの機能がありました。
spec/factories/item.rb
下手なことをするよりも、これで3つずつ計12個レコードを作成すればよさそうです。
呼ぶ時は先ほどと同様にcreateやcreate_listでいけます。
spec/models/item_spec.rb
spec/factories/item.rb
FactoryGirl.define do
factory :item do
sequence(:name) { |n| "sample#{n}" }
trait category_1 do
category 1
end
trait category_2 do
category 2
end
trait category_3 do
category 3
end
trait category_4 do
category 4
end
end
factory :item_content_1, traits: [:category_1], parent: :item
factory :item_content_2, traits: [:category_2], parent: :item
factory :item_content_3, traits: [:category_3], parent: :item
factory :item_content_4, traits: [:category_4], parent: :item
end
親を:itemとして、属性を付加します。下手なことをするよりも、これで3つずつ計12個レコードを作成すればよさそうです。
呼ぶ時は先ほどと同様にcreateやcreate_listでいけます。
spec/models/item_spec.rb
require 'rails_helper'
RSpec.describe Item, type: :model do
context 'itemのレコードが存在するとき' do
before do
FactoryGirl.create_list(:item_content_1, 3)
# もしくはこんな感じ(createならばその他の値も設定できるので、融通がききます。)
3.times { FactoryGirl.create(:item_content_2) }
end
# 省略
end
end
もしもっと良い方法をご存知の方がいらっしゃいましたら教えてください!
余談:sequenceに初期値を設定する
ちなみにsequenceには初期値が設定できます。
といっても簡単で、第2引数に値を設定します。(何も指定しなければ1です。)
といっても簡単で、第2引数に値を設定します。(何も指定しなければ1です。)
# 100番からスタート
sequence(:name, 100) { |n| "sample#{n}" }
0 件のコメント:
コメントを投稿