はじめに
RSpecでモデルのテストは書けるようになってきたけど、画面の操作ってどうやってテストも実装したい。
そこで使えるのが Capybara です。
Capybaraとは?
Capybaraは、ブラウザの操作をシミュレートできるツールです。
「ページを開いて、フォームに入力して、ボタンを押して、結果を確認する」という、実際のユーザーが行う操作をテストコードで再現できます。これを システムスペック と呼びます。
セットアップ
Gemfileに追加します。
# Gemfile
group :development, :test do
gem 'capybara'
end
追加したら bundle install を実行します。
spec/rails_helper.rb に以下が含まれているか確認しましょう。Rails 5.1以降ならデフォルトで入っていることが多いです。
require 'capybara/rspec'
基本的な書き方
Capybaraを使ったテストは type: :system で書きます。
RSpec.describe "ユーザー登録", type: :system do
it "正しい情報を入力すると登録できる" do
visit new_user_registration_path # ページを開く
fill_in "名前", with: "田中太郎" # フォームに入力
fill_in "メールアドレス", with: "tanaka@example.com"
fill_in "パスワード", with: "password123"
click_button "登録する" # ボタンをクリック
expect(page).to have_content "登録が完了しました" # 表示を確認
end
end
日本語でそのまま書けるので、「何をテストしているか」がわかりやすいですね。
よく使うメソッド
| メソッド | 説明 |
|---|---|
visit パス |
指定のページを開く |
fill_in "ラベル名", with: "値" |
フォームに文字を入力する |
click_button "ボタン名" |
ボタンをクリックする |
click_link "リンク名" |
リンクをクリックする |
expect(page).to have_content "文字" |
ページにその文字があるか確認する |
expect(page).to have_current_path パス |
現在のURLを確認する |
テスト内での使用例
ログインのテスト
RSpec.describe "ログイン", type: :system do
it "正しい情報でログインできる" do
# あらかじめユーザーをDBに作っておく
User.create(email: "tanaka@example.com", password: "password123")
visit login_path
fill_in "メールアドレス", with: "tanaka@example.com"
fill_in "パスワード", with: "password123"
click_button "ログイン"
expect(page).to have_content "ログインしました"
end
it "間違ったパスワードではログインできない" do
User.create(email: "tanaka@example.com", password: "password123")
visit login_path
fill_in "メールアドレス", with: "tanaka@example.com"
fill_in "パスワード", with: "wrong_password"
click_button "ログイン"
expect(page).to have_content "メールアドレスまたはパスワードが違います"
end
end
FactoryBotと組み合わせる
前の記事で紹介したFactoryBotと組み合わせると、ユーザーの作成部分がさらにスッキリします。
RSpec.describe "ログイン", type: :system do
let(:user) { create(:user) }
it "正しい情報でログインできる" do
visit login_path
fill_in "メールアドレス", with: user.email
fill_in "パスワード", with: "password123"
click_button "ログイン"
expect(page).to have_content "ログインしました"
end
end
User.create(...) と書いていた部分が create(:user) の1行になりました。
before を使ってまとめる
複数のテストで同じログイン操作が必要なとき、before を使うとまとめて書けます。
RSpec.describe "記事投稿", type: :system do
let(:user) { create(:user) }
before do
visit login_path
fill_in "メールアドレス", with: user.email
fill_in "パスワード", with: "password123"
click_button "ログイン"
end
it "記事を投稿できる" do
visit new_article_path
fill_in "タイトル", with: "初めての記事"
fill_in "本文", with: "こんにちは!"
click_button "投稿する"
expect(page).to have_content "記事を投稿しました"
end
it "タイトルがなければ投稿できない" do
visit new_article_path
fill_in "本文", with: "こんにちは!"
click_button "投稿する"
expect(page).to have_content "タイトルを入力してください"
end
end
before ブロックの中の処理は、各テストの前に自動的に実行されます。
まとめ
| メソッド | 説明 |
|---|---|
visit |
ページを開く |
fill_in |
フォームに入力する |
click_button / click_link
|
ボタン・リンクをクリックする |
have_content |
ページに文字があるか確認する |
before |
各テストの前に共通処理をまとめる |
Capybaraを使うと、「実際にブラウザで操作したらどうなるか」をテストコードで確認できます。FactoryBotと組み合わせるとさらに書きやすくなるので、ぜひ一緒に使ってみてください。