RSpec场景重构

RSpec scenario refactoring

有一些 RSpec 集成测试:

require 'spec_helper'

feature 'Authentication', js: true do
  scenario 'Successfully Sign In' do
    user = create(:user)
    visit '/admin/signin'
    expect(page).to have_content('Login to Admin Panel')
    fill_in 'Email', with: user.email
    fill_in 'Password', with: user.password
    click_button 'Login'
    expect(page).to have_content('Welcome to the administrative panel of "Hotels" service!')
  end

  scenario 'Failed Sign In' do
    user = create(:user)
    visit '/admin/signin'
    expect(page).to have_content('Login to Admin Panel')
    fill_in 'Email', with: user.email + '_wrong'
    fill_in 'Password', with: user.password
    click_button 'Login'
    expect(page).to have_content('Invalid username/password')
  end

  scenario 'Repeated Sign In' do
    user = create(:user)
    visit '/admin/signin'
    expect(page).to have_content('Login to Admin Panel')
    fill_in 'Email', with: user.email
    fill_in 'Password', with: user.password
    click_button 'Login'
    visit '/admin/signin'
    expect(page).to have_content('Welcome to the administrative panel of "Hotels" service!')
  end

  scenario 'Sign Out' do
    user = create(:user)
    visit '/admin/signin'
    expect(page).to have_content('Login to Admin Panel')
    fill_in 'Email', with: user.email
    fill_in 'Password', with: user.password
    click_button 'Login'
    click_link 'Sign out'
    expect(page).to have_content('Login to Admin Panel')    
  end
end

正如你所看到的,这些测试非常相似,我希望有一些重构它的能力。我听说过shared_examples,但我对场景中的这个概念不太了解。请给我一些建议,我可以如何改进我的功能测试。谢谢!

我会把那些重复的代码放在 helper 文件/spec/support/这样

module Features
  module SessionHelpers
    def sign_in(email, password)  
    visit '/admin/signin'
    expect(page).to have_content('Login to Admin Panel')
    fill_in 'Email', with: email
    fill_in 'Password', with: password
    click_button 'Login'
    end
  end
end

然后在每个场景中像这样调用该方法

scenario 'Successfully Sign In' do
   user = create(:user)
   sign_in(user.email, user.password)
   expect(page).to have_content('Welcome to the administrative panel of "Hotels" service!')
end

除了@Pavan 的回答,在这种情况下你绝对应该使用 before :each,所以你的整个测试将是这样的:

feature 'Authentication', js: true do
   before :each do
      user = create(:user)
      sign_in(user.email, user.password)
   end

   scenario 'Successfully Sign In' do
      expect(page).to have_content('Welcome to the administrative panel of "Hotels" service!')
   end

   scenario 'Repeated Sign In' do
      visit '/admin/signin'
      expect(page).to have_content('Welcome to the administrative panel of "Hotels" service!')
   end

   scenario 'Sign Out' do
      click_link 'Sign out'
      expect(page).to have_content('Login to Admin Panel')    
   end
 end

您可以阅读更多关于 Rspec before/after 钩子 here