はじめに
サービスの品質を保つために必要不可欠なテストを実施しております。
今回はいいね機能の結合テストを実装し、その実装内容を記事にしていきたいと思います。
前提
・Like(いいね)モデルの単体テストは実施済み
※完了されていない方や単体テストと並行してご覧になられたい方は、以下のLikeモデルの単体テストについての記事をご参考ください。
バージョン
rubyのバージョン ruby-2.6.5
Railsのバージョン Rails:6.0.0
rspec-rails 4.0.0
実施したテスト
likesテーブルのカラムの紹介
xxx_create_likes.rb
class CreateLikes < ActiveRecord::Migration[6.0]
def change
create_table :likes do |t|
t.references :user, foreign_key: true
t.references :answer, foreign_key: true
t.references :definition, foreign_key: true
t.timestamps
end
end
end
「いいね」に関するviewの内容
app/views/definitions/show.html.erb
# 〜省略〜
<% if current_user.already_liked?(answer) %>
<%= link_to definition_answer_likes_path(@definition,answer), method: :delete do %>
<i class="fas fa-heart", id="liking-btn"></i>
<% end %>
<% else %>
<%= link_to definition_answer_likes_path(@definition,answer), method: :post do %>
<i class="far fa-heart", id="nolike-btn"></i>
<% end %>
<% end %>
<%= answer.likes.count %>
<%= "(#{time_ago_in_words(answer.created_at)}前)" %>
# 〜省略〜
モデル内のバリデーション
app/models/like.rb
class Like < ApplicationRecord
belongs_to :user
belongs_to :answer
belongs_to :definition
validates :user_id, presence: true
validates :answer_id, uniqueness: { scope: :user_id }, presence: true
validates :definition_id, uniqueness: { scope: :user_id }, presence: true
end
FactoryBotの内訳
spec/factories/likes.rb
FactoryBot.define do
factory :like do
association :answer
association :definition
user { answer.user }
end
end
サポートモジュール
spec/support/sign_in_support.rb
module SignInSupport
def sign_in(user)
visit user_session_path
fill_in 'user[email]', with: user.email
fill_in 'user[password]', with: user.password
find('input[name="commit"]').click
expect(current_path).to eq(root_path)
end
end
テストコードの内容
spec/system/likes_spec.rb
require 'rails_helper'
RSpec.describe "Likes", type: :system do
before do
@definition = FactoryBot.create(:definition)
@answer = FactoryBot.create(:answer)
end
describe '#create,#destroy' do
it 'ユーザーが他の投稿をいいね、いいね解除できる' do
# ログインする
sign_in(@definition.user)
# 投稿詳細ページに遷移する
visit definition_path(@definition.id)
# フォームに情報を入力する
fill_in 'answer_answer', with: @answer
# 回答を送信すると、Answerモデルのカウントが1上がることを確認する
expect{
find('input[name="commit"]').click
}.to change { Answer.count }.by(1)
# いいねをするボタンを押す
find('#nolike-btn').click
expect(page).to have_selector '#liking-btn'
expect(@answer.likes.count).to eq(1)
# いいねを解除する
find('#liking-btn').click
expect(page).to have_selector '#nolike-btn'
expect(@answer.likes.count).to eq(0)
end
end
end
補足説明
find().clickについて
今回、引数の値はview内のいいねボタンのidの要素となります。
app/views/definitions/show.html.erb
# 〜省略〜
<i class="fas fa-heart", id="liking-btn"></i>
# 〜省略〜
<i class="far fa-heart", id="nolike-btn"></i>
# 〜省略〜
have_selectorについて
have_selector 〜の〜内に特定の要素を含んでいるか検査します。
なので、
spec/system/likes_spec.rb
expect(page).to have_selector '#liking-btn'
pageでvisitで訪れた先のページのことで、そのページ内にliking-btnのidの要素を含んでいるかの確認をしています。
expect( ).to eq( )について
AnswerモデルとLikeモデルはアソシエーションで紐付けているので
spec/system/likes_spec.rb
expect(@answer.likes.count).to eq(1)
likesテーブル内のカラムのcount数は1となるという意味になります。
以上です。