在rails 4中重构rspec特性测试代码的麻烦

时间:2013-12-05 02:09:11

标签: ruby-on-rails ruby rspec capybara

我试图让我的网络应用程序的用户能够使用密码登录。我正在滚动自己的身份验证而不是使用gem。我读了这篇关于重构Rspec / Capybara测试的文章:

http://robots.thoughtbot.com/rspec-integration-tests-with-capybara

我喜欢我读到的内容,并决定尝试重构。我为我的功能测试创建了一个会话帮助文件。

module Features
  module SessionHelpers
    def sign_in
      user = create(:user)
      visit '/authentications/new'
      fill_in 'Login', with: user.name
      fill_in 'Password', with:  user.password
     click_button 'Sign in'
   end
 end
end

然后我在登录测试中调用了sign_in函数。这是一个小样本。

require 'spec_helper'

feature "signing in" do
  before :each do
    User.create(:name => 'user@example.com', :password => 'caplin')
  end

  scenario "user who logs in with correct credentials" do
    sign_in
    expect(page).to have_content 'Hi user@example.com'
  end
end

不幸的是,我不断收到此错误消息:

2) signing in user who logs in with correct credentials
     Failure/Error: sign_in
     NoMethodError:
       undefined method `create' for #<RSpec::Core::ExampleGroup::Nested_3:0x007ffc85012438>
     # ./spec/support/features/session_helpers.rb:4:in `sign_in'
     # ./spec/features/user_logs_in_spec.rb:13:in `block (2 levels) in <top (required)>'

基本上,我需要一些方法来抓取我创建的用户并将其传递给sign_in函数。任何提示?

3 个答案:

答案 0 :(得分:4)

我猜你的第一个问题是与WhileBot示例不同的测试配置。 create我不知道RSpec中提供的默认方法;我猜他们已经将每个FactoryGirl方法添加到测试范围。如果您正在使用FactoryGirl,只需命名创建命令即可获得相同的行为:

 def sign_in
   user = FactoryGirl.create(:user)
   visit '/authentications/new'
   fill_in 'Login', with: user.name
   fill_in 'Password', with:  user.password
   click_button 'Sign in'
 end

然而,由于您仍然无法添加自定义用户,因此无法完全满足您的要求。一个简单的方法是允许用户传入:

def sign_in(user=nil)
  user ||= FactoryGirl.create(:user)
  ...
end

如果您未在sign_in来电中传入,则会为您创建用户。

回到您发布的规范,您需要将其更改为:

feature "signing in" do
  before :each do
    @user = User.create(:name => 'user@example.com', :password => 'caplin')
  end

  scenario "user who logs in with correct credentials" do
    sign_in(@user)
    expect(page).to have_content 'Hi user@example.com'
  end
end

您需要将您创建的用户附加到变量(@user),然后根据需要将其传递给sign_in

答案 1 :(得分:0)

你模型中的问题

module Features
  module SessionHelpers
    def sign_in
      user = create(:user) # <- this method allow only in FactoryGirl
      visit '/authentications/new'
      fill_in 'Login', with: user.name
      fill_in 'Password', with:  user.password
     click_button 'Sign in'
   end
 end
end

我用另一种方式。创建一个类并包含FactroyGirl方法和Capybara::DSL这样的

class Features
  include FactoryGirl::Syntax::Methods
  include Capybara::DSL

  def sign_in
    user = create(:user)                     #<- FactroyGirl
    visit '/authentications/new'             #<- Capybara
    fill_in 'Login', with: user.name         #<- Capybara
    fill_in 'Password', with:  user.password #<- Capybara
    click_button 'Sign in'                   #<- Capybara
    self                                     #<- return page
  end
end

在规范中

feature "signing in" do
  let(:login_user) { Features.new }

  scenario "user who logs in with correct credentials" do
    page = login_user.sign_in
    expect(page).to have_content 'Hi user@example.com'
  end
end

答案 2 :(得分:0)

您可以通过在测试中包含FactoryGirl来实现此目的。您的RSpec配置块(在spec_helper.rb或RSpec rails_helper.rb的新版本中)应如下所示:

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end