RSpec 다 대 다 관계 모델 테스트 (예 : 태그 모델)
18385 단어 RSpecRailsFactoryBot태그루비
소개
rspec의 태그 모델 테스트를 할 때 중간 테이블 (post_tag)을 통한 방식에 고전했기 때문에,
factory_bot을 이용하여 다대다관계(has_many through)의 테스트 작성 방법을 설명하겠습니다.
테이블
post
와 tag
사이에 post_tag
테이블이 있는 상태입니다.
도달점
다음 2점 달성
· 중간 테이블을 통한 모델 테스트의 FactoryBot 이해
· 중간 테이블을 통한 모델 테스트 작성 방법 이해
흐름
① 각 모델의 validates를 확인
② FactoryBot의 기술
③ 모델 테스트 설명
① 각 모델의 validates를 확인
app/models/post.rbclass Post < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :tags, through: :post_tags
validates :title,
presence: true,
length: { maximum: 60 }
validates :body,
presence: true,
length: { maximum: 2000 }
end
app/models/post.rbclass Tag < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :posts, through: :post_tags
validates :name, presence: true, length: { maximum: 50 }
end
app/models/post.rbclass PostTag < ApplicationRecord
belongs_to :post
belongs_to :tag
validates :post_id, presence: true
validates :tag_id, presence: true
② FactoryBot의 기술
app/spec/factories/post.rbFactoryBot.define do
factory :post do
sequence(:title) { |n| "title-#{n}" }
sequence(:body) { |n| "body-#{n}" }
after(:create) do |post|
create_list(:post_tag, 1, post: post, tag: create(:tag))
end
end
end
after(:create)
를 사용하면 post 생성 후 tag와 post_tag가 생성됩니다.
app/spec/factories/tag.rbFactoryBot.define do
factory :tag do
sequence(:name) { |n| "tag-#{n}" }
end
end
sequence
로 고유 이름을 생성할 수 있습니다.
app/spec/factories/post_tag.rbFactoryBot.define do
factory :post_tag do
association :post
association :tag
end
end
association :post
association :tag
로 하는 것으로,
post_tag의 모델 테스트에서let(:post_tag) { create(:post_tag) }
post와 tag도 생성할 수 있습니다.
다만, asociation은 has_many
측(이번 경우,post,tag)에서는 기술하지 않고,belong_to
측에서만 사용합시다.
③ 모델 테스트 설명
app/spec/requests/post.rbRSpec.describe Post, type: :model do
let(:post) { create(:post) }
it "タイトル、本文、user_idがある場合、有効であること" do
expect(post).to be_valid
end
it "user_idがない場合、無効であること" do
post.user_id = nil
expect(post).to be_invalid
end
describe "タイトル" do
it "タイトルがない場合、無効であること" do
post.title = nil
expect(post).to be_invalid
expect(post.errors[:title]).to include("を入力してください")
end
context "タイトルが60文字以下の場合" do
it "有効であること" do
post.title = "1" * 60
expect(post).to be_valid
end
end
context "タイトルが61文字以上の場合" do
it "無効であること" do
post.title = "1" * 61
expect(post).to be_invalid
end
end
end
describe "本文" do
it "本文がない場合、無効であること" do
post.body = nil
expect(post).to be_invalid
expect(post.errors[:body]).to include("を入力してください")
end
context "本文が2000文字以下の場合" do
it "有効であること" do
post.body = "1" * 2000
expect(post).to be_valid
end
end
context "本文が2001文字以上の場合" do
it "無効であること" do
post.body = "1" * 2001
expect(post).to be_invalid
end
end
end
end
app/spec/requests/tag.rbRSpec.describe Tag, type: :model do
let(:tag) { create(:tag) }
describe "name" do
it "タグ名がある場合、有効であること" do
expect(tag).to be_valid
end
it "タグ名がない場合、無効であること" do
tag.name = nil
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("を入力してください")
end
context "タグ名が50文字以下の場合" do
it "有効であること" do
tag.name = "1" * 50
expect(tag).to be_valid
end
end
context "タグ名が51文字以上の場合" do
it "無効であること" do
tag.name = "1" * 51
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("は50文字以内で入力してください")
end
end
end
end
app/spec/requests/post_tag.rbRSpec.describe PostTag, type: :model do
let(:post_tag) { create(:post_tag) }
it "post_idとtag_idがある場合、有効であること" do
expect(post_tag).to be_valid
end
it "post_idがない場合、無効であること" do
post_tag.post_id = nil
expect(post_tag).to be_invalid
end
it "tag_idがない場合、無効であること" do
post_tag.tag_id = nil
expect(post_tag).to be_invalid
end
end
association
으로 let(:post_tag) { create(:post_tag) }
가 한 문장으로 완료되었습니다.
덧붙여 it나 context내의 문장은, 영어라면 철자 미스 등이 나올 가능성이 있기 때문에, 기본 일본어로 하고 있습니다.
실수 등이 있으시면 지적하신 분 잘 부탁드립니다.
참고 기사
FactoryBot (FactoryGirl) 치트 시트
factory_girl에서 최소한 알고 싶은 4 가지 사용법
FactoryBot(구 FactoryGirl)로 관련 데이터를 동시에 생성하는 방법 여러가지
Reference
이 문제에 관하여(RSpec 다 대 다 관계 모델 테스트 (예 : 태그 모델)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/holdout0521/items/6de7b50549f8f7f952ca
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
다음 2점 달성
· 중간 테이블을 통한 모델 테스트의 FactoryBot 이해
· 중간 테이블을 통한 모델 테스트 작성 방법 이해
흐름
① 각 모델의 validates를 확인
② FactoryBot의 기술
③ 모델 테스트 설명
① 각 모델의 validates를 확인
app/models/post.rbclass Post < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :tags, through: :post_tags
validates :title,
presence: true,
length: { maximum: 60 }
validates :body,
presence: true,
length: { maximum: 2000 }
end
app/models/post.rbclass Tag < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :posts, through: :post_tags
validates :name, presence: true, length: { maximum: 50 }
end
app/models/post.rbclass PostTag < ApplicationRecord
belongs_to :post
belongs_to :tag
validates :post_id, presence: true
validates :tag_id, presence: true
② FactoryBot의 기술
app/spec/factories/post.rbFactoryBot.define do
factory :post do
sequence(:title) { |n| "title-#{n}" }
sequence(:body) { |n| "body-#{n}" }
after(:create) do |post|
create_list(:post_tag, 1, post: post, tag: create(:tag))
end
end
end
after(:create)
를 사용하면 post 생성 후 tag와 post_tag가 생성됩니다.
app/spec/factories/tag.rbFactoryBot.define do
factory :tag do
sequence(:name) { |n| "tag-#{n}" }
end
end
sequence
로 고유 이름을 생성할 수 있습니다.
app/spec/factories/post_tag.rbFactoryBot.define do
factory :post_tag do
association :post
association :tag
end
end
association :post
association :tag
로 하는 것으로,
post_tag의 모델 테스트에서let(:post_tag) { create(:post_tag) }
post와 tag도 생성할 수 있습니다.
다만, asociation은 has_many
측(이번 경우,post,tag)에서는 기술하지 않고,belong_to
측에서만 사용합시다.
③ 모델 테스트 설명
app/spec/requests/post.rbRSpec.describe Post, type: :model do
let(:post) { create(:post) }
it "タイトル、本文、user_idがある場合、有効であること" do
expect(post).to be_valid
end
it "user_idがない場合、無効であること" do
post.user_id = nil
expect(post).to be_invalid
end
describe "タイトル" do
it "タイトルがない場合、無効であること" do
post.title = nil
expect(post).to be_invalid
expect(post.errors[:title]).to include("を入力してください")
end
context "タイトルが60文字以下の場合" do
it "有効であること" do
post.title = "1" * 60
expect(post).to be_valid
end
end
context "タイトルが61文字以上の場合" do
it "無効であること" do
post.title = "1" * 61
expect(post).to be_invalid
end
end
end
describe "本文" do
it "本文がない場合、無効であること" do
post.body = nil
expect(post).to be_invalid
expect(post.errors[:body]).to include("を入力してください")
end
context "本文が2000文字以下の場合" do
it "有効であること" do
post.body = "1" * 2000
expect(post).to be_valid
end
end
context "本文が2001文字以上の場合" do
it "無効であること" do
post.body = "1" * 2001
expect(post).to be_invalid
end
end
end
end
app/spec/requests/tag.rbRSpec.describe Tag, type: :model do
let(:tag) { create(:tag) }
describe "name" do
it "タグ名がある場合、有効であること" do
expect(tag).to be_valid
end
it "タグ名がない場合、無効であること" do
tag.name = nil
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("を入力してください")
end
context "タグ名が50文字以下の場合" do
it "有効であること" do
tag.name = "1" * 50
expect(tag).to be_valid
end
end
context "タグ名が51文字以上の場合" do
it "無効であること" do
tag.name = "1" * 51
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("は50文字以内で入力してください")
end
end
end
end
app/spec/requests/post_tag.rbRSpec.describe PostTag, type: :model do
let(:post_tag) { create(:post_tag) }
it "post_idとtag_idがある場合、有効であること" do
expect(post_tag).to be_valid
end
it "post_idがない場合、無効であること" do
post_tag.post_id = nil
expect(post_tag).to be_invalid
end
it "tag_idがない場合、無効であること" do
post_tag.tag_id = nil
expect(post_tag).to be_invalid
end
end
association
으로 let(:post_tag) { create(:post_tag) }
가 한 문장으로 완료되었습니다.
덧붙여 it나 context내의 문장은, 영어라면 철자 미스 등이 나올 가능성이 있기 때문에, 기본 일본어로 하고 있습니다.
실수 등이 있으시면 지적하신 분 잘 부탁드립니다.
참고 기사
FactoryBot (FactoryGirl) 치트 시트
factory_girl에서 최소한 알고 싶은 4 가지 사용법
FactoryBot(구 FactoryGirl)로 관련 데이터를 동시에 생성하는 방법 여러가지
Reference
이 문제에 관하여(RSpec 다 대 다 관계 모델 테스트 (예 : 태그 모델)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/holdout0521/items/6de7b50549f8f7f952ca
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Post < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :tags, through: :post_tags
validates :title,
presence: true,
length: { maximum: 60 }
validates :body,
presence: true,
length: { maximum: 2000 }
end
class Tag < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :posts, through: :post_tags
validates :name, presence: true, length: { maximum: 50 }
end
class PostTag < ApplicationRecord
belongs_to :post
belongs_to :tag
validates :post_id, presence: true
validates :tag_id, presence: true
app/spec/factories/post.rb
FactoryBot.define do
factory :post do
sequence(:title) { |n| "title-#{n}" }
sequence(:body) { |n| "body-#{n}" }
after(:create) do |post|
create_list(:post_tag, 1, post: post, tag: create(:tag))
end
end
end
after(:create)
를 사용하면 post 생성 후 tag와 post_tag가 생성됩니다.app/spec/factories/tag.rb
FactoryBot.define do
factory :tag do
sequence(:name) { |n| "tag-#{n}" }
end
end
sequence
로 고유 이름을 생성할 수 있습니다.app/spec/factories/post_tag.rb
FactoryBot.define do
factory :post_tag do
association :post
association :tag
end
end
association :post
association :tag
로 하는 것으로,post_tag의 모델 테스트에서
let(:post_tag) { create(:post_tag) }
post와 tag도 생성할 수 있습니다.다만, asociation은
has_many
측(이번 경우,post,tag)에서는 기술하지 않고,belong_to
측에서만 사용합시다.③ 모델 테스트 설명
app/spec/requests/post.rbRSpec.describe Post, type: :model do
let(:post) { create(:post) }
it "タイトル、本文、user_idがある場合、有効であること" do
expect(post).to be_valid
end
it "user_idがない場合、無効であること" do
post.user_id = nil
expect(post).to be_invalid
end
describe "タイトル" do
it "タイトルがない場合、無効であること" do
post.title = nil
expect(post).to be_invalid
expect(post.errors[:title]).to include("を入力してください")
end
context "タイトルが60文字以下の場合" do
it "有効であること" do
post.title = "1" * 60
expect(post).to be_valid
end
end
context "タイトルが61文字以上の場合" do
it "無効であること" do
post.title = "1" * 61
expect(post).to be_invalid
end
end
end
describe "本文" do
it "本文がない場合、無効であること" do
post.body = nil
expect(post).to be_invalid
expect(post.errors[:body]).to include("を入力してください")
end
context "本文が2000文字以下の場合" do
it "有効であること" do
post.body = "1" * 2000
expect(post).to be_valid
end
end
context "本文が2001文字以上の場合" do
it "無効であること" do
post.body = "1" * 2001
expect(post).to be_invalid
end
end
end
end
app/spec/requests/tag.rbRSpec.describe Tag, type: :model do
let(:tag) { create(:tag) }
describe "name" do
it "タグ名がある場合、有効であること" do
expect(tag).to be_valid
end
it "タグ名がない場合、無効であること" do
tag.name = nil
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("を入力してください")
end
context "タグ名が50文字以下の場合" do
it "有効であること" do
tag.name = "1" * 50
expect(tag).to be_valid
end
end
context "タグ名が51文字以上の場合" do
it "無効であること" do
tag.name = "1" * 51
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("は50文字以内で入力してください")
end
end
end
end
app/spec/requests/post_tag.rbRSpec.describe PostTag, type: :model do
let(:post_tag) { create(:post_tag) }
it "post_idとtag_idがある場合、有効であること" do
expect(post_tag).to be_valid
end
it "post_idがない場合、無効であること" do
post_tag.post_id = nil
expect(post_tag).to be_invalid
end
it "tag_idがない場合、無効であること" do
post_tag.tag_id = nil
expect(post_tag).to be_invalid
end
end
association
으로 let(:post_tag) { create(:post_tag) }
가 한 문장으로 완료되었습니다.
덧붙여 it나 context내의 문장은, 영어라면 철자 미스 등이 나올 가능성이 있기 때문에, 기본 일본어로 하고 있습니다.
실수 등이 있으시면 지적하신 분 잘 부탁드립니다.
참고 기사
FactoryBot (FactoryGirl) 치트 시트
factory_girl에서 최소한 알고 싶은 4 가지 사용법
FactoryBot(구 FactoryGirl)로 관련 데이터를 동시에 생성하는 방법 여러가지
Reference
이 문제에 관하여(RSpec 다 대 다 관계 모델 테스트 (예 : 태그 모델)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/holdout0521/items/6de7b50549f8f7f952ca
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
RSpec.describe Post, type: :model do
let(:post) { create(:post) }
it "タイトル、本文、user_idがある場合、有効であること" do
expect(post).to be_valid
end
it "user_idがない場合、無効であること" do
post.user_id = nil
expect(post).to be_invalid
end
describe "タイトル" do
it "タイトルがない場合、無効であること" do
post.title = nil
expect(post).to be_invalid
expect(post.errors[:title]).to include("を入力してください")
end
context "タイトルが60文字以下の場合" do
it "有効であること" do
post.title = "1" * 60
expect(post).to be_valid
end
end
context "タイトルが61文字以上の場合" do
it "無効であること" do
post.title = "1" * 61
expect(post).to be_invalid
end
end
end
describe "本文" do
it "本文がない場合、無効であること" do
post.body = nil
expect(post).to be_invalid
expect(post.errors[:body]).to include("を入力してください")
end
context "本文が2000文字以下の場合" do
it "有効であること" do
post.body = "1" * 2000
expect(post).to be_valid
end
end
context "本文が2001文字以上の場合" do
it "無効であること" do
post.body = "1" * 2001
expect(post).to be_invalid
end
end
end
end
RSpec.describe Tag, type: :model do
let(:tag) { create(:tag) }
describe "name" do
it "タグ名がある場合、有効であること" do
expect(tag).to be_valid
end
it "タグ名がない場合、無効であること" do
tag.name = nil
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("を入力してください")
end
context "タグ名が50文字以下の場合" do
it "有効であること" do
tag.name = "1" * 50
expect(tag).to be_valid
end
end
context "タグ名が51文字以上の場合" do
it "無効であること" do
tag.name = "1" * 51
expect(tag).to be_invalid
expect(tag.errors[:name]).to include("は50文字以内で入力してください")
end
end
end
end
RSpec.describe PostTag, type: :model do
let(:post_tag) { create(:post_tag) }
it "post_idとtag_idがある場合、有効であること" do
expect(post_tag).to be_valid
end
it "post_idがない場合、無効であること" do
post_tag.post_id = nil
expect(post_tag).to be_invalid
end
it "tag_idがない場合、無効であること" do
post_tag.tag_id = nil
expect(post_tag).to be_invalid
end
end
FactoryBot (FactoryGirl) 치트 시트
factory_girl에서 최소한 알고 싶은 4 가지 사용법
FactoryBot(구 FactoryGirl)로 관련 데이터를 동시에 생성하는 방법 여러가지
Reference
이 문제에 관하여(RSpec 다 대 다 관계 모델 테스트 (예 : 태그 모델)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/holdout0521/items/6de7b50549f8f7f952ca텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)