こんにちは、watanabeです。 RSpecの学習ブログの第二回です。
今回はファクトリ編のおまけです。データを作る際のテクニックだったり、DRYにする方法をまとめます。
同じクラスのファクトリを複数定義する
ファクトリは複数定義ができます。 同じクラス内で命名が異なるファクトリをクラスを指定して記述できます。
FactoryBot.define do factory :project do sequence(:name) { |n| "Project #{n}" } description { "A test project." } due_on { 1.week.from_now } association :owner # 昨日が締め切りのプロジェクト factory :project_due_yesterday, class: Project do sequence(:name) { |n| "Test Project #{n}" } description { "Sample project for testing purposes" } due_on { 1.day.ago } association :owner end end
ファクトリの継承をつかう
親クラスのファクトリの中で、さらにファクトリを定義することで継承をつかうこともできます。 そのまま継承する値は特になにもせずともOKで、定義を変更する属性のみを記述します。
FactoryBot.define do factory :project do sequence(:name) { |n| "Project #{n}" } description { "A test project." } due_on { 1.week.from_now } association :owner # 今日が締め切りのプロジェクト factory :project_due_today do due_on { Date.current.in_time_zone } end end end
traitで集合を表現する
trait ファクトリ名 do ~ end
でファクトリの集合を表現できます。
定義は継承とほぼ同じでベースとなるファクトリに対して、異なる属性値のみを定義します。
FactoryBot.define do factory :project do sequence(:name) { |n| "Project #{n}" } description { "A test project." } due_on { 1.week.from_now } association :owner # 今日が締め切りのプロジェクト factory :project_due_today do due_on { Date.current.in_time_zone } end end # 締切が明日 trait :due_tomorrow do due_on { 1.day.from_now } end # 昨日が締め切りのプロジェクト factory :project_due_yesterday, class: Project do sequence(:name) { |n| "Test Project #{n}" } description { "Sample project for testing purposes" } due_on { 1.day.ago } association :owner end end
traitの場合はテストサイドでの呼び出し方法が変わり、FactoryBot.create( クラス名, trait名)
で呼び出せます(※.createに限りません)。
コールバックをつかう
ファクトリにはbeforeやafterといったコールバックが用意されていて、オブジェクト生成の前後に実行する処理を定義できます。
FactoryBot.define do factory :project do sequence(:name) { |n| "Project #{n}" } description { "A test project." } due_on { 1.week.from_now } association :owner # メモ付きのプロジェクト trait :with_notes do after(:create) { |project| create_list(:note, 5, project: project)} end end
この例の場合はベースとなるprojectオブジェクトが生成後に noteオブジェクトが生成されます。create_list
は引数で指定したオブジェクトを指定した個数分生成します。
ブロックを取るので定義の処理はワンラインでも複数行でも記述できます。
DRYよりも可読性ではないかと
そんな感じでFactoryでデータを作る時の方法を書いてきました。今回はそのまま参考書から抜粋した内容が多いのでごくごく初歩的な方法ばかりです。 とはいえ、コールバックを多用したり、いくつもファクトリを定義したりすると容易に可読性は落ちてしまうと思います。テストはまずは通ること、そしてメンテナンスのコストが低いことが重要だと思いますのでDRYはほどほどに書けるといいんじゃないでしょうか。
教材はこちら
RSpec初心者の教材としては定番?の「Everyday Rails - RSpecによるRailsテスト入門」を使っています。 フィヨルドブートキャンプのメンター兼ソニックガーデンのエンジニアをされている伊藤淳一さんが訳をされています。 Rails7に対応修正した初心者〜中級者向けの内容となっているので信頼度が高いかなと思います。