Everyday Rails - RSpecによるRailsテスト入門 まとめ2
beforeについて
beforeブロックを使うとdescribeやcontextブロックの内部で、各テストの実行前に共通のインスタンス変数をセットアップできる。beforeの中に書いたコードはdescribeやcontextの内部に書いたテストを実行するたびに毎回実行される。
デメリット1
使う必要のないデータを作成してテストを遅くする原因になることもある。
デメリット2
要件が増えるにつれてテストの可読性を悪くする。
こうした問題に対処するため、RSpecはletというメソッドがある。
letは呼ばれたときに初めてデータを読み込む、遅延読み込みを実現する
メソッドであり、beforeブロックでテストデータをセットアップする際は、インスタンス変数に格納していたが、letではインスタンスへ格納しない。
■訂正前
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
click_button "新規登録"
expect(page).to have_content("ユーザの登録に失敗しました。")
end
end
end
■訂正中
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(:password) { "password" }
let(:password_confirmation) { "password" }
it "ユーザーを登録できる" do
expect(page).to have_content "登録に成功しました。"
end
end
context "全ての項目が入力されていない場合" do
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(: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(: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(: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" }
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. 新規登録時に名前とメールアドレス、パスワード、パスワード(確認)とあるがその組わせを全てテストするものではなく、特定の場合のフラッシュが表示されるかをテストしないと意味がない。共通のフラッシュである、登録に失敗しましたのメッセージだけをテストすることに意味がない。