Ruby on Rails チュートリアルの第4版を学習し、Everyday Rails - RSpecによるRailsテスト入門でRSpecを学習したので、Ruby on Rails チュートリアルをRSpecでテストしてみました。
今回は第3章~第6章までを書きます。
Railsチュートリアル第3~5章のテスト
今回はHomeページのみテストしました。(Help、About、Contactページはテストしない。)
まず初めに
$ bin/rails g rspec:feature static_page
でspec/features/static_pages_spec.rbを作成し、Homeページが正しく表示されていること、タイトルが正しいことをテストします。
require 'rails_helper'
RSpec.feature "StaticPages", type: :feature do
describe "Home page" do
before do
visit root_path # 名前付きルートを使用
end
# HomeページにStaticPages#homeと表示されていること
it "should have the content 'StaticPages#home'" do
expect(page).to have_content "StaticPages#home"
end
# タイトルが正しく表示されていること
it "should have the right title" do
expect(page).to have_title full_title('')
end
end
end
さらに、spec/support/utilities.rbを作成しfull_titleメソッドを定義します。
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
"#{base_title} | #{page_title}"
end
end
実行するとテストがパスします。
StaticPages
Home page
should have the content 'StaticPages#home'
should have the right title
Finished in 0.27791 seconds (files took 0.22495 seconds to load)
2 examples, 0 failures
spec/support/utilities.rb
が自動で読み込まれない場合は、RSpec3でspec/support内のファイルを読み込むを参考にしてください。
同じように新規登録ページもテストします。
require 'rails_helper'
RSpec.feature "UserPages", type: :feature do
describe "signup page" do
before do
visit signup_path
end
# 新規登録ページに"Sign up"と表示されていること
it "should have the content 'Sign up'" do
expect(page).to have_content "Sign up"
end
# タイトルが正しく表示されていること
it "should have the right title" do
expect(page).to have_title full_title('Sign up')
end
end
end
Railsチュートリアル第6章のテスト
続いてUserモデルのバリデーションをテストしていきます。
ファクトリを使ってテストデータのセットアップを行うためにGemfileにFactory Botをインストールします。
また、テストを簡略化するためにShoulda Matchersを使用します。
(gemのバージョンはEveryday Rails - RSpecによるRailsテスト入門を参照しました。)
group :development, :test do
gem 'rspec-rails', '~> 3.6.0'
gem 'factory_bot_rails', '~> 4.10.0'
・・・
end
group :test do
# 他のgemは省略
gem 'shoulda-matchers',
git: 'https://github.com/thoughtbot/shoulda-matchers.git',
branch: 'rails-5'
end
さらに、Shoulda Matchersを使用するためにspec/rails_helper.rbの一番最後に以下のコードを追加します。
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
コードを追加したら
$ bin/rails g factory_bot:model user
でspec/factories/users.rbを作成し、以下のようにテストデータを作成します。
FactoryBot.define do
factory :user do
name "Example"
sequence(:email) { |n| "tester#{n}@example.com" }
password "password"
password_confirmation "password"
end
end
続いてspec/models/user_spec.rbを作成し、name、email、passwordのバリデーションをテストします。
require 'rails_helper'
RSpec.describe User, type: :model do
let(:user) { FactoryBot.create(:user) }
describe User do
# 有効なファクトリを持つこと
it "has a valid factory" do
expect(user).to be_valid
end
end
# Shoulda Matchers を使用
it { is_expected.to validate_presence_of :name }
it { is_expected.to validate_length_of(:name).is_at_most(50) }
it { is_expected.to validate_presence_of :email }
#it { is_expected.to validate_uniqueness_of(:email).case_insensitive } ・・・(*)
it { is_expected.to validate_length_of(:email).is_at_most(255) }
it { is_expected.to validate_presence_of :password }
it { is_expected.to validate_length_of(:password).is_at_least(6) }
# 重複したメールアドレスなら無効な状態であること ・・・(*)
it "is invalid with a duplicate email adress" do
FactoryBot.create(:user, email: "aaron@example.com")
user = FactoryBot.build(:user, email: "Aaron@example.com")
user.valid?
expect(user.errors[:email]).to include("has already been taken")
end
# メールアドレスの有効性
describe "email validation should reject invalid addresses" do
# 無効なメールアドレスの場合
it "should be invalid" do
invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
foo@bar_baz.com foo@bar+baz.com]
invalid_addresses.each do |invalid_address|
user.email = invalid_address
expect(user).to_not be_valid
end
end
# 有効なメールアドレスの場合
it "should be valid" do
valid_addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn]
valid_addresses.each do |valid_address|
user.email = valid_address
expect(user).to be_valid
end
end
end
# パスワード確認が一致すること
describe "when password doesn't match confirmation" do
# 一致する場合
it "is valid when password confirmation matches password" do
user = FactoryBot.build(:user, password: "password", password_confirmation: "password")
expect(user).to be_valid
end
# 一致しない場合
it "is invalid when password confirmation doesn't match password" do
user = FactoryBot.build(:user, password: "password", password_confirmation: "different")
user.valid?
expect(user.errors[:password_confirmation]).to include("doesn't match Password")
end
end
end
メールアドレスの重複のテスト(*)はShoulda Matchersを使うと上手くいかなかったので、通常のテスト(簡略化していない)を実行しました。
テストを実行してパスするのを確認します。
Finished in 0.09507 seconds (files took 0.15479 seconds to load)
12 examples, 0 failures
今回は以上です。
第7章以降のテストは完成しだい書いていきます。
#追記
第7章以降のテストを書きました。
- Railsチュートリアルの第4版をRSpecでテスト-2(第7章~第8章)
- Railsチュートリアルの第4版をRSpecでテスト-3(第9章)
- Railsチュートリアルの第4版をRSpecでテスト-4(第10章)
- Railsチュートリアルの第4版をRSpecでテスト-5(第11章)
- Railsチュートリアルの第4版をRSpecでテスト-6(第12章)