bin/rails g factory_bot:model user
A file that creates data with FactoryBot is generated as in. This time, the following files will be generated in spec / factories / users.rb
.
spec/factories/users.rb
FactoryBot.define do
factory :user do
end
end
I will pack the data I want to create in this.
spec/factories/users.rb
FactoryBot.define do
factory :user do
name {"Sato"}
age {20}
height {170}
end
end
spec/models/user.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it "is valid with a name, age and height" do
expect(FactoryBot.build(:user)).to be_valid
end
end
You can write it concisely like this. By the way, if you don't use FactoryBot, it will be as follows.
spec/models/user.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it "is valid with a name, age and height" do
user = User.new(
name: "Sato",
age: 20,
height: 170,
)
expect(user).to be_valid
end
end
It will look like this, and the number of lines will increase.
That said, it's easier to read, but it hides the data inside FactoryBot, so choose whether to use it or not, depending on your use case.
You can override the data in the file where you write the specs.
spec/models/user.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it "is invalid without a name" do
user = FactoryBot.build(:user, name: nil)
user.vaild?
expect(user.errors[:name]).to include("can't be blank")
end
end
Overwrite the contents of FactoryBot and change name
to nil
.
For example, "email address" should be a unique value. However, if you use FactoryBot as it is, the same value will be entered every time, so it will get stuck in validation. (Unintentionally.)
A "sequence" is provided to address that issue.
spec/factories/users.rb
FactoryBot.define do
factory :user do
name {"Sato"}
age {20}
height {170}
#A sequence is used for email.
sequence(:email) {|n| "test#{n}@example.com"}
end
end
This will allow you to always enter a unique value such as [email protected]
, [email protected]
each time a new user is created.
For example, suppose you want to test an elderly person, or a tall person. The small problem can be absorbed in the factory. There are two main methods.
spec/factories/users.rb
FactoryBot.define do
factory :user do
name {"Sato"}
age {20}
height {170}
sequence(:email) {|n| "test#{n}@example.com"}
#Data for the elderly
factory :senior do
age {75}
end
#Data for tall people
factory :tall do
height {190}
end
end
end
You can use it like FactoryBot.build (: user,: senior)
or FactoryBot.build (: user,: tall)
.
I like this one better. The reason is that it can be shortened by writing it in ** FactoryBot **, ** you can see what is "different" **. Let's take a look anyway!
spec/factories/users.rb
FactoryBot.define do
factory :user do
name {"Sato"}
age {20}
height {170}
sequence(:email) {|n| "test#{n}@example.com"}
trait :senior do
age {75}
end
trait :tall do
height {190}
end
end
end
You can call it by writing something like FactoryBot.build (: user,: senior)
.
By doing this, the ** features ** of the data are clearly shown, so it is highly readable, isn't it?
Factory Bot can also represent dynamic movements. Take a look at the code below.
spec/factories/users.rb
FactoryBot.define do
factory :user do
name {"Sato"}
age {20}
height {170}
sequence(:email) {|n| "test#{n}@example.com"}
trait :with_tasks do
after(:create) { |user| create_list(:task, 5, user: user) }
end
end
end
You can create tasks related to user by doing FactoryBot.build (: user,: with_tasks)
.