RSpec学習メモ(everyday Rails RSpecによるRailsテスト入門 第4章)
<アプリケーションにファクトリを追加する>
$ bundle exec rails g factory_bot model:user
# specディレクトリ内にfactoriesという新しいディレクトリが作られる。そしてその中にusers.rbという名前のファイルが作成される。
<spec/factories/users.rb>
FactoryBot.define do
factory :user do
first_name "Aaron"
last_name "Sumner"
email "tester@example.com"
password "dottle-nouveau-pavilion-tights-furze"
end
end
こうすると、テスト内でFactoryBot.create(:user)と書くことで新しいユーザーを作成することができる。
FactoryBot.create(:user)を使ってテストデータを作れば、そのユーザーは毎回基本的に上記で設定したデータのものとなる。
<spec/models/user_spec.rb>
describe User do
# 有効なファクトリを持つこと
it "has a valid factory" do
expect(FactoryBot.build(:user)).to be_valid
end
end
FactoryBotを使用することでこのように簡潔に書き換えることができる。
ここではFactoryBot.buildを使用したので、新しいユーザーはインスタンス化されるだけで、保存はされない。
ポイント
FactoryBot.buildを使うと新しいテストオブジェクトをメモリ内に保存する。FactoryBot.createを使うとアプリケーションのテスト用データベースにオブジェクトを永続化する。
---------------------------------------------------------------------------------------
<シーケンスを使ってユニークなデータを作成する>
FactoryBotではシーケンスを使って、ユニークバリデーションを持つフィールドを扱うことができる。
<spec/factories/users.rb>
FactoryBot.define do
factory :user do
first_name "Aaron"
last_name "Sumner"
sequence(:email) { |n| "tester#{n}@example.com" }
password "dottle-nouveau-pavilion-tights-furze"
end
end
新しいユーザーを作成するたびに、、tester1@example.com 、tester2@example.com というように、ユニークで連続したメールアドレスが設定される。
---------------------------------------------------------------------------------------
<ファクトリ関連を扱う>
FactoryBotは他のモデルと関連を持つモデルを扱うのにとても便利である。
<spec/factories/users.rb>
FactoryBot.define do
factory :user, aliases: [:owner] do
first_name "Aaron"
last_name "Sumner"
sequence(:email) { |n| "tester#{n}@example.com" }
password "dottle-nouveau-pavilion-tights-furze"
end
end
<spec/factories/notes.rb>
FactoryBot.define do
factory :note do
message "My important note."
association :project
user { project.owner }
end
end
<spec/factories/projects.rb>
FactoryBot.define do
factory :project do
sequence(:name) { |n| "Project #{n}" }
description "A test project."
due_on 1.week.from_now
association :owner
end
end
Noteはプロジェクトとユーザーの両方に属している。しかし、テストのたびに毎回プロジェクトとユーザーを手作業で作成したくはない。今作りたいのはメモだけである。
ポイント
FactoryBotを使用する際は、ユーザーファクトリに対してownerという名前で参照される場合があると伝えなくてはならない。そのためにaliasを使用する。
<app/models/project.rb>
class Project < ApplicationRecord
validates :name, presence: true, uniqueness: { scope: :user_id }
belongs_to :owner, class_name: User, foreign_key: :user_id
has_many :tasks
has_many :notes
end
---------------------------------------------------------------------------------------
<ファクトリ内の重複をなくす>
FactoryBotでは同じ型を作成するファクトリを複数定義することもできる。
特定のファクトリを使って作成するインスタンスのクラス名と、既存のファクトリと異なるインスタンスの属性値を指定する。そしてその作成したインスタンスの名前を引数に渡すことができる。
重複を減らすテクニックが二つある。
①ファクトリの継承を使ってユニークな属性だけを変えること。
②トレイと(trait)を使ってテストデータを構築すること。
---------------------------------------------------------------------------------------
<ファクトリを安全に使用する>
ファクトリを使用するとテスト中に予期しないデータが作成されたり、無駄にテストが遅くなったりする原因となる。
可能な限りFactoryBot.createではなくFactoryBot.buildを使用することで、テストデータベースにデータを追加する回数が減るので、パフォーマンス面のコストを削減することができる。