dreamin' blog

associationをデフォルトのfactoryではnilを渡す

一般的にFactoryBotは大きなプロジェクトになってくると無駄なデータを作成する可能性が増えてきます。
例えば、こんな時。

factory :tag do
  article
end

it do
  create_list(:tag, 10)
  # 10個タグがある場合のなんらかのテスト
end

articleがtagを複数持てるDB構造になっているとして、
tagが10個以上付いているページのfeature specなどを書きたい場合がある時に、
上記のような書き方をしてしまうと、tagが10個だけできればいいものの、articleも10個できてしまうのです。

これを抑制するために、

factory :tag do
  article { nil }
end

このようにartilceは敢えてnilを渡して、validateエラーが起こるようにしておきます。
そうするとうっかり、 create_list(:tag, 10) なんて書いてもテストが落ちるようになり、、

it do
  create(: article)
  create_list(:tag, 10, article: article)
  # 10個タグがある場合のなんらかのテスト
end

おそらく、このようなテストになってくれるはずです。

あくまでデフォルトの話であって、traitを使う分には特定のcontextの名前を入れることができるので、問題ないと考えています。

factory :tag do
  trait :with_article do
    article
  end
end

↑みたいなのはOK

FactoryBot.lintの困るところ

で、この方針でfactorybotを運用すると困ることがあり、、
FactoryBot.lintは factory_botで作成されたDBテスト用のファイルの治安を守るためのFactoryBotがデフォルトで持っているlint機構です。

factory :tag do

  article { nil }
end

何と、こんなFactoryBot.lintは許されないのです。
validateエラーを敢えて起こしているのに、validateエラーになっちゃう。

ので、 strategy: :build のオプションを使ったlintを実行しています。
しかしながら、buildのlintは意味があるような無いような。。。
そもそも、関連にnilを渡すようにするのって多分気持ち悪いって方が多い気もします。(僕も最近まではそうでした。

皆さんはどのようにFactoryBot.lintを運用されていますか??