Everyday Rails - RSpecによるRailsテスト入門 まとめ2

beforeについて

beforeブロックを使うとdescribeやcontextブロックの内部で、各テストの実行前に共通のインスタンス変数をセットアップできる。beforeの中に書いたコードはdescribeやcontextの内部に書いたテストを実行するたびに毎回実行される。

 

デメリット1

使う必要のないデータを作成してテストを遅くする原因になることもある。

 デメリット2

要件が増えるにつれてテストの可読性を悪くする。

 

 

こうした問題に対処するため、RSpecはletというメソッドがある。

letは呼ばれたときに初めてデータを読み込む、遅延読み込みを実現する

メソッドであり、beforeブロックでテストデータをセットアップする際は、インスタンス変数に格納していたが、letではインスタンスへ格納しない。 

 

 

■訂正前

require 'rails_helper'

RSpec.describe "Users"type: :system do
  
  let(:user) { build :user }
  
  context "新規登録をクリック" do
    it "新規登録ページに遷移" do
      visit root_path
      click_on "新規登録"
      expect(page).to have_content("新規登録")
    end
  end
 
  context "入力項目に正しい値を入力" do
    it "ユーザー登録できる" do
      user = build(:user,name: "test",email: "test@example.com"password: "abcdefg"password_confirmation: "abcdefg")
      visit signup_path

      fill_in "お名前"with: user.name
      fill_in "メールアドレス"with: user.email
      fill_in "パスワード"with: user.password
      fill_in "パスワード(確認)"with: user.password_confirmation
      click_button "新規登録"
      expect(page).to have_content("登録に成功しました。")
    end    
  end

  context "入力項目に誤った値を入力" do
    it "エラーメッセージが表示される" do
      visit signup_path

      fill_in "お名前"with: nil
      fill_in "メールアドレス"with: nil
      fill_in "パスワード"with: nil
      fill_in "パスワード(確認)"with: nil
      click_button "新規登録"
      expect(page).to have_content("ユーザの登録に失敗しました。")
    end
  end
end

 

 

 

■訂正中 

require 'rails_helper'

RSpec.describe "Users"type: :system do
  
  let(:user) { build :user }
  
  context "新規登録をクリック" do
    it "新規登録ページに遷移" do
      visit root_path
      click_on "新規登録"
      expect(page).to have_content("新規登録")
    end
  end
 
  context "amazonListを始めるをクリック" do
    it "新規登録ページに遷移" do
      visit root_path
      click_on "amazonListを始める"
      expect(page).to have_content("新規登録")
    end
  end

  describe "ユーザー登録" do
    before do
      visit signup_path
      fill_in "お名前"with: name
      fill_in "メールアドレス"with: email
      fill_in "パスワード"with: password
      fill_in "パスワード(確認)"with: password_confirmation
      click_button "新規登録"
    end

    context "正しい値を入力した場合" do
      let(:name) { "tanaka taro" }
      let(:email) { "taro@example.com" }
      let(:password) { "password" }
      let(:password_confirmation) { "password" }

      it "ユーザーを登録できる" do
        expect(page).to have_content "登録に成功しました。"
      end
    end
    
    context "全ての項目が入力されていない場合" do
      let(:name) { nil }
      let(:email) { nil }
      let(:password) { nil }
      let(:password_confirmation) { nil }
      
      it "エラーメッセージが表示される" do
        expect(page).to have_content "ユーザの登録に失敗しました。"
        expect(page).to have_content "Nameを入力してください"
        expect(page).to have_content "Emailを入力してください"
        expect(page).to have_content "Emailは不正な値です"
        expect(page).to have_content "Passwordを入力してください"
      end
    end
    
    context "名前のみ入力されていない場合" do
      let(:name) { nil }
      let(:email) { "yamada@yahoo.co.jp" }
      let(:password) { "test123" }
      let(:password_confirmation) { "test123" }
      
      it "エラーメッセージが表示される" do
        expect(page).to have_content "ユーザの登録に失敗しました。"
        expect(page).to have_content "Nameを入力してください"
      end
    end

    context "emailのみ入力されていない場合" do
      let(:name) { "yamada sinichiro" }
      let(:email) { nil }
      let(:password) { "aiueokaki" }
      let(:password_confirmation) { "aiueokaki" }
      
      it "エラーメッセージが表示される" do
        expect(page).to have_content "ユーザの登録に失敗しました。"
        expect(page).to have_content "Emailを入力してください"
        expect(page).to have_content "Emailは不正な値です"
      end
    end
    
    context "パスワードのみ入力されていない場合" do
      let(:name) { "kato yuki" }
      let(:email) { "kato@outlook.com" }
      let(:password) { nil }
      let(:password_confirmation) { "katoyuki" }
      
      it "エラーメッセージが表示される" do
        expect(page).to have_content "ユーザの登録に失敗しました。"
        expect(page).to have_content "Passwordを入力してください"
      end
    end

    context "パスワード(確認)のみ入力されていない場合" do
      let(:name) { "suzuki ai" }
      let(:email) { "suzuki@ai.com" }
      let(:password) { "SUzuki$123" }
      let(:password_confirmation) { nil }
      
      it "エラーメッセージが表示される" do
        expect(page).to have_content "ユーザの登録に失敗しました。"
        expect(page).to have_content "Password confirmationとPasswordの入力が一致しません"
      end
    end
  end
end

 

 

訂正したこと

 

1.共通の動作をまとめた。describe,before, contextの使い方。

describe "ユーザー登録" do
  before do
    visit signup_path
    fill_in "お名前", with: name
    fill_in "メールアドレス", with: email
    fill_in "パスワード", with: password
    fill_in "パスワード(確認)", with: password_confirmation
    click_button "新規登録"
  end

  context "正しい値を入力した場合" do
    let(:name) { "tanaka taro" }
    let(:email) { "taro@example.com" }
    let(:password) { "password" }
    let(:password) { "password" }

    it "ユーザーを登録できる" do
        expect(page).to have_content "登録に成功しました。"
    end
  end

 

 2. 新規登録時に名前とメールアドレス、パスワード、パスワード(確認)とあるがその組わせを全てテストするものではなく、特定の場合のフラッシュが表示されるかをテストしないと意味がない。共通のフラッシュである、登録に失敗しましたのメッセージだけをテストすることに意味がない。