結合テストコードの書き方(Rails)


今回はRailsでの結合テストコードの記述の仕方を記事にしたいと思います。
開発したオリジナルアプリのコードを元に説明したいと思います。

なお、FactoryBotとFakerを導入済みです

はじめに

単体テストコードでは、RspecというGemを導入しました。
結合テストコードでは、System Specという技術とCapybaraというGem
が必要です。
しかし、これらはデフォルトで導入済みです。

Gemfile

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
end

Gemfileを確認すると、Capybaraが導入されていることがわかります。

Gemが導入されていることがわかったので、次はターミナルよりファイルを作成します。

% rails g rspec:system users

system/user_spec.rbが作成されていることが確認できます。

今回はユーザー新規登録ができる時のテストコードを書いていきたいと思います。
まずは、example洗い出します。

system/user_spec.rb

describe "新規登録できる時" do
      it "正しい情報が登録できれば新規登録ができてトップページに遷移する" do
        # トップページに移動する
        # トップページに新規登録へ遷移のボタンがあることを確認する        
        # 新規登録ページへ移動する
        # ユーザー情報を入力する
        # 新規登録ボタンをクリックするとユーザーカウントが1上がる
        # トップページへ遷移したことを確認する
        # トップページに新規登録ボタンやログインボタンがないことを確認する
      end
    end

ユーザー目線で、どのように操作するか考えながらexampleを洗い出します。

コードの記述

一項目ずつ説明したいと思います。

# トップページに移動する
   visit root_path

・visit
visitを使用しpathを指定するとページに移動します。

# トップページに新規登録へ遷移のボタンがあることを確認する
  expect(page).to have_content("新規登録")

これは、ページの中に新規登録の文字列が含まれているかを判断します。
文字れるの確認には、have_contentのマッチャを使用します。
ちなみに、画像の場合はhave_selectorを使用します。

# 新規登録ページへ移動する
  visit new_user_registration_path
# ユーザー情報を入力する
  fill_in "メールアドレス", with: @user.email
  fill_in "パスワード(半角英数混合6文字以上)", with: @user.password, match: :first
  fill_in "パスワード再入力", with: @user.password_confirmation, match: :first
  fill_in "nickname", with: @user.nickname
  fill_in "プロフィール(自分を一言で表現してください)", with: @user.profile

「ユーザー情報入力」の部分、フォームへの入力はfill_inをを使用します。

fill_in 'フォームの名前', with: '入力する文字列'

のように記述することで、フォームへの入力を行うことができます。
フォームの名前の入力には検証ツールを使用します。

label要素のforに指定されているIDと、inputのidの値が同一になっています。
各フォームがlabelで紐付いていることがわかります。
フォームの名前が「メールアドレス」ということがわかるので、抜き出しました。
この要領で抜き出す部分を探します。

入力する文字列は、@userの中にはFactoryBotで設定した情報が入っていて、
.emailとつけることによってemailの情報を入力しています。

# 新規登録ボタンをクリックするとユーザーカウントが1上がる
  expect{
  find('input[name="commit"]').click
  }.to change { User.count }.by(1)

新規登録が完了すし、ユーザーが1人増えることを確認しています。

・find().click
find('クリックしたい要素').clickと記述することで、実際にクリックができます。
つまりフォームを入力した後に、登録完了ボタンを押すということです。
これも検証ツールで確認することができます。


この部分のどこかしらを指定してあげれば大丈夫です。

・change
expect{ 何かしらの動作 }.to change { モデル名.count }.by(1)と記述することによって、モデルのレコードの数がいくつ変動するのかを確認できます。changeマッチャでモデルのカウントをする場合のみ、expect()ではなくexpect{}となります。

クリックして、ユーザーが1人増えたことを確認しているわけですね。
changeの時だけ、expect{}になるは忘れそうなので要チャックです。

# トップページへ遷移したことを確認する
  expect(current_path).to eq(root_path)
# トップページに新規登録ボタンやログインボタンがないことを確認する
  expect(page).to have_no_content("ログイン")
  expect(page).to have_no_content("新規登録")

新規登録が完了した後は、トップページに移動するように処理を記述しています。
なので、移動した現在のページ(current_path)がトップページ(root_path)で
あることを確認しています。

そして、ログイン状態のトップページには、「ログイン」「新規登録ボタン」がない
ことを確認することにより、新規登録が完了しログイン状態になっていることが確認できます。
have_no_contentはhave_contentとは逆でないことを確認します。

以上が一部ですが、結合テストコードの書き方です。
色々書きましたが、これらは調べれば出てくるので
暗記する必要はなく大事なのは、意味を理解することだと学びました。

もし何か間違った記述や気になることありましたらコメント残して頂ければ幸いです。