FactoryGirlの使い方はググればすぐ出て来るんだけど、「適切」な使い方、いわゆるベストプラクティスを紹介、あるいは模索しているページは日本語ではほとんどない(英語だとちょくちょくある、たとえば「FactoryGirl slow」でググってみると良いと思う)。テストの改善を任されたのでせっかくだからその記録をここに残しておくことでFactoryGirlのより良い書き方の議論が盛り上がるようなことになればうれしいな、と思う。
アンチパターン1:とにかくcreate
SQLアンチパターンみたくかっこいい二つ名をつけたかった気もするけど後で超絶恥ずかしくなるのはわかってるので、そのままの名付けをしていく。
とにかくすべてcreate
、create_list
を使うというパターン。本当に実際の環境をエミュレートしていることに間違いはないのだけど、とにかく遅い。IOを両方行っているし、単一のobjectならいざ知らず、巨大関連からなる一つの「系統樹」とでもいうべき一連のobjectを一つのexampleのたびにDBIOするのはどう考えても無駄なコストだ。特にただ単にメソッドの振る舞いをテストするようなときはbuild
、build_stubbed
で十分だと思われる。むしろデフォルトをbuild
、build_stubbed
にして問題が発生したときに初めてcreate
を使うことを考慮する、くらいでいいかもしれない。
参考:https://robots.thoughtbot.com/speed-up-tests-by-selectively-avoiding-factory-girl
https://robots.thoughtbot.com/use-factory-girls-build-stubbed-for-a-faster-test)
アンチパターン2:異常に根深いassociationと遠隔操作のごときtrait
上にも少し話題にあげたけど、あまりassociationを深くしすぎると融通が利かなくなるので、二段階異常のassociationについてはstubメソッドで対応する、みたいにしたほうがいい気がする。そして、これをtraitで管理するとどういう風になるのかというと、
Model One
belongs_to Two
belongs_to Three
Model Two
#a/bの二種類を取りうる
Model Three
#c/dの二種類を取りうる
Model Four
belongs_to Two
#e/fの二種類を取りうる
みたいな関連になってるときに、
with_Two_is_a_and_Four_is_e_and~
みたいな直接ではない関連を制御するためのtraitが出てきだす。そうなると辛くて、すべてのパターンを網羅するようにfactoryを定義していく義務みたいなのが生じてくる。しかし、一段階より大きい深さの関連についてはstubでごまかす、みたいな風にしとくと、factory自体はそこまで複雑にならずに済む。factoryの定義とテストが密結合だと、今までは同じfactoryで済んでたケースが仕様が変わってあるケースだけ先のほうの関連objectの何かしらの設定を変更しないといけない、となったときに、trait職人みたいになってくるのはつらい。やはりfactoryは直接関連しているobjectにのみ責任を持つべきだと思う。(デメテルの法則)
TODO:これについて書く(ちゃんと読む)。
ご意見や新たなアンチパターン、ベストプラクティスをお待ちしております。この記事は加筆修正していく予定です。