4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ruby on Rails】結合テストコードについてまとめ(Capybara)

Posted at

初学者です。
テストコードがなぜか大好きです。

今回は結合テストコードについてまとめます。
Capybaraという標準で導入されているGemを利用しています。

前提条件

  • FactoryBotを導入済みである

上記については以下の記事にまとめています。
【Ruby on Rails】FactoryBotとFakerについてまとめ

テストコードの種類

  • 単体テストコード

モデルやコントローラーなど機能ごとに問題がないか確認します。
例えばバリデーションがきちんと動作しているかなどです。

  • 結合テストコード

ユーザーがブラウザで操作する一連の流れを再現して問題がないか確かめます。
例えば、ユーザー登録で「名前とメールアドレスとパスワードを入力するとトップページに遷移して表示がユーザーの名前に変わっている」などの一連の動作を確認します。

  • 正常系

ユーザーが開発者の意図する操作を行った時の挙動を確認するテストコードです。
例えば、ユーザー登録で問題なく全てのデータが入力された場合などです。

  • 異常系

ユーザーが開発者の意図しない操作を行った時の挙動を確認するテストコードです。
例えば、ユーザー登録で正しい値が入っていないと登録できないかどうかなどです。

準備

今回はUserモデルの結合テストコードを例にしていきます。

まずは下記コマンドで結合テストコードを書くファイルを準備します。

ターミナル
rails g rspec:system users

spec/system配下にusers_spec.rbというファイルが生成されていればOKです。

テストコード

解説はあとにして先に記述例を載せます。

spec/system/users_spec.rb
require 'rails_helper'

RSpec.describe 'ユーザー新規登録', type: :system do
  before do
    @user = FactoryBot.build(:user)
  end
  context 'ユーザー新規登録ができるとき' do 
    it '正しく情報を入力すればユーザー新規登録ができてトップページに移動する' do
      # トップページに移動する
      visit root_path
      # トップページに新規登録ページへ遷移するボタンがあることを確認する
      expect(page).to have_content('新規登録')
      # 新規登録ページへ移動する
      visit new_user_registration_path
      # ユーザー情報を入力する
      fill_in 'name', with: @user.nickname
      fill_in 'Email', with: @user.email
      fill_in 'Password', with: @user.password
      fill_in 'Password confirmation', with: @user.password_confirmation
      # 登録ボタンを押すとユーザーモデルのカウントが1増えることを確認する
      expect{
        find('input[name="button"]').click
      }.to change { User.count }.by(1)
      # トップページへ遷移することを確認する
      expect(current_path).to eq(root_path)
      # カーソルを合わせるとログアウトボタンが表示されることを確認する
      expect(
        find('.user_nav').find('span').hover
      ).to have_content('ログアウト')
      # 新規登録ページへ遷移するボタンやログインページへ遷移するボタンが表示されていないことを確認する
      expect(page).to have_no_content('新規登録')
      expect(page).to have_no_content('ログイン')
    end
  end
  context 'ユーザー新規登録ができないとき' do
    it '誤った情報ではユーザー新規登録ができずに新規登録ページへ戻ってくる' do
      # トップページに移動する
      visit root_path
      # トップページに新規登録ページへ遷移するボタンがあることを確認する
      expect(page).to have_content('新規登録')
      # 新規登録ページへ移動する
      visit new_user_registration_path
      # ユーザー情報を入力する
      fill_in 'name', with: ''
      fill_in 'Email', with: ''
      fill_in 'Password', with: ''
      fill_in 'Password confirmation', with: ''
      # 登録ボタンを押してもユーザーモデルのカウントが増えないことを確認する
      expect{
        find('input[name="button"]').click
      }.to change { User.count }.by(0)
      # 新規登録ページへ戻されることを確認する
      expect(current_path).to eq('/users')
    end
  end
end

RSpec.describe 'ログイン', type: :system do
  before do
    @user = FactoryBot.create(:user)
  end
  context 'ログインができるとき' do
    it '保存されているユーザーの情報と合致すればログインができる' do
      # トップページに移動する
      visit root_path
      # トップページにログインページへ遷移するボタンがあることを確認する
      expect(page).to have_content('ログイン')
      # ログインページへ遷移する
      visit new_user_session_path
      # 正しいユーザー情報を入力する
      fill_in 'Email', with: @user.email
      fill_in 'Password', with: @user.password
      # ログインボタンを押す
      find('input[name="button"]').click
      # トップページへ遷移することを確認する
      expect(current_path).to eq(root_path)
      # カーソルを合わせるとログアウトボタンが表示されることを確認する
      expect(
        find('.nav_bar').find('span').hover
      ).to have_content('ログアウト')
      # サインアップページへ遷移するボタンやログインページへ遷移するボタンが表示されていないことを確認する
      expect(page).to have_no_content('新規登録')
      expect(page).to have_no_content('ログイン')
    end
  end
  context 'ログインができないとき' do
    it '保存されているユーザーの情報と合致しないとログインができない' do
      # トップページに移動する
      visit root_path
      # トップページにログインページへ遷移するボタンがあることを確認する
      expect(page).to have_content('ログイン')
      # ログインページへ遷移する
      visit new_user_session_path
      # ユーザー情報を入力する
      fill_in 'Email', with: ''
      fill_in 'Password', with: ''
      # ログインボタンを押す
      find('input[name="button"]').click
      # ログインページへ戻されることを確認する
      expect(current_path).to eq(new_user_session_path)
    end
  end
end

まずdescribe新規登録の場合とログインの場合で項目分けします。

次にcontextでそれぞれ正常系と異常系で項目分けします。

そのあと、それぞれの流れを書いていきます。

FactoryBotについては新規登録はbuildですが、ログインはユーザー情報があらかじめあることが前提なのでcreateにしています。

では内容について細かく解説していきます。

visit

トップページに移動するvisit root_pathとしています。
visitは遷移するという意味で利用します。

page

visitで訪れた先のページの情報が格納されています。例えばカーソルを合わせてはじめて見ることができる文字列はpageの中に含まれません。

have_content

トップページに新規登録ページへ遷移するボタンがあることを確認するexpect(page).to have_content('新規登録')としています。
visitで訪れたpageの中に該当の文字列があるかどうかを判断する時に利用します。

fill_in

ユーザー情報を入力するfill_inを利用しています。
fill_in フォームの名前, with: 入力する文字列と記述することでフォームへの入力を行うことができます。

find().click

find(クリックしたい要素).clickと記述することでクリックの動作ができます。

登録ボタンを押すとユーザーモデルのカウントが1増えることを確認する登録ボタンを押すの動作をfind('input[name="button"]').clickで表しています。
この場合はinput要素のname="button"を指定していることになります。

change

expect{ 動作 }.to change { モデル名.count }.by(1)登録ボタンを押すとユーザーモデルのカウントが1増えることを確認する
カウントが1増えるを表しています。

current_path

トップページへ遷移することを確認するexpect(current_path).to eq(root_path)としています。
current_path今いるページという意味です。

hover

find(要素).hoverで特定の要素にカーソルをあわせたときの動作を表すことができます。
カーソルを合わせるとログアウトボタンが表示されることを確認するexpect(find('.nav_bar').find('span').hover).to have_content('ログアウト')としています。
今回の場合は.nav_barの中のspan要素という感じで二重に探しています。

have_no_content

サインアップページへ遷移するボタンやログインページへ遷移するボタンが表示されていないことを確認するexpect(page).to have_no_content('新規登録')expect(page).to have_no_content('ログイン')としています。
存在しないことを確認するという意味です。

以上です。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?