17
23

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.

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

Last updated at Posted at 2019-01-08

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章以降のテストを書きました。

17
23
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
17
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?