'[email protected]' } let(:user) { User.create(email: verified_email) } # Good 最低限の情報から意図が伝わる it 'confirms user email' do user.confirm_email expect(user.email_confirmed?).to be true end # Good 意味のある単位で分割する it 'updates last_login_time' do # ... end
モデルスペックで確認したことをコントローラースペックでも確かめる (バリデーション) describe 'POST #create' do it 'creates a new user' do post :create, params: { user: { name: 'Alice' } } expect(assigns(:user)).to be_valid # これはモデルのテスト end it 'does not create a user' do post :create, params: { user: { name: nil } } expect(assigns(:user)).not_to be_valid end end
コントローラーの責務に焦点を当てたテスト describe 'POST #create' do it 'redirects to the user page on successful creation' do allow_any_instance_of(User).to receive(:valid?).and_return(true) post :create, params: { user: { name: 'Alice' } } expect(response).to redirect_to(user_path(assigns(:user))) # コントローラーの責務 end it 'renders new template on failure' do allow_any_instance_of(User).to receive(:valid?).and_return(false) post :create, params: { user: { name: 'Alice' } } expect(response).to render_template(:new) end end
全ての行が落ちる場合、1行毎にしか気づけない it "creates a user with correct attributes" do user = create_user!(name: 'Alice', email: '[email protected]', age: 23) expect(user.name).to eq 'Alice' # ここで落ちると後続が実行されない! expect(user.email).to eq '[email protected]' # 全て誤りであれば3回テストを往復する必要がある expect(user.age).to eq 23 end
# Good 一つのテストケースで確かめる事柄を1つにする it "creates a user with correct name" do user = create_user!(name: 'Alice') expect(user.name).to eq 'Alice' end it "creates a user with correct email" do # 他のテストケース成否に関係なく実行される # ... end
# Good テストユーティリティを使う it "creates a user with correct attributes" do user = create_user!(name: 'Alice', email: '[email protected]', age: 23) expect(user).to have_attributes( # attributesの差分を1度に確認できる name: 'Alice', email: '[email protected]', age: 23 ) end
Test Patterns の Test Smell > Cause を見る と良いです ◦ 例. Obscure Test > Cause: General Fixture • p.25 「どこでエラーになってるんだ...」については他にも原因がありえます ◦ Erratic Test (確率的に落ちる) ◦ Fragile Test (何もしてないのに壊れる) ◦ これらのケースは対処が特殊で話すと長いのであえて割愛