Help us understand the problem. What is going on with this article?

Railsチュートリアルの第4版をRSpecでテスト-1

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ページが正しく表示されていること、タイトルが正しいことをテストします。

spec/features/static_pages.rb
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メソッドを定義します。

spec/support/utilities.rb
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内のファイルを読み込むを参考にしてください。

同じように新規登録ページもテストします。

spec/features/user_pages_spec.rb
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テスト入門を参照しました。)

Gemfile.
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の一番最後に以下のコードを追加します。

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を作成し、以下のようにテストデータを作成します。

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のバリデーションをテストします。

spec/models/user_spec.rb
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章)

IrieLuka
2019年の3月に大学院を卒業し、4月から機械系エンジニアとして働いています。 ブログでは英語学習、YouTubeでは機械エンジニアの仕事内容や社会人1年目で学んだことについて発信しています。
https://hmsrmaster.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした