2017-04-07 74 views
0

我的目的是为相同的表单创建一些测试,并且在这些测试中,我需要Capybara完全填写表单。不过,我想避免重写填写表单的代码。如何在Rails中进行测试DRY并仍使用Capybara和Warden? (使用minitest)

我没有使用RSPEC!我正在使用minitest。

我面临的问题是不能从我的CapybaraHelper模块访问水豚方法visit和守望者帮手方法login_as

我见过这个问题,所以我在test/support文件夹中创建了我的模块,但我提到的方法仍然无法访问。 How to reuse code in Capybara

我已经看到了这个问题,但我想重用的代码似乎并没有在setup方法也不在teardown方法合身。 Rails: Premake a model instance for your unit tests (for DRY purposes)?

我也看到了帖子说这个模块应该是里面test_helper.rb,但我添加更多的模块,这个文件就会变得混乱。

所以现在我想知道我做错了什么。我试过在CapybaraHelper中加入以下几行,但没有帮助。它实际上提出了错误NoMethodError: undefined method设置为CapybaraHelper:模块。

include Devise::Test::ControllerHelpers 
include Warden::Test::Helpers 

在测试中重用代码是否正确?我是否缺少应该包含在我的帮助模块中的内容?所有这些方法都可以在使用CapybaraHelper:Module的测试控制器中正常工作。

以下是错误消息:

NoMethodError: undefined method `login_as' for CapybaraHelper:Module 

这里是使用CapybaraHelper:Module另一个测试的错误消息。

NoMethodError: undefined method `visit' for CapybaraHelper:Module 

这里是我的测试:

require 'test_helper' 

class TravelsControllerTest < ActionController::TestCase 
    include Devise::Test::ControllerHelpers 
    include Warden::Test::Helpers 
    Warden.test_mode! 

    test 'should accept correct fields' do 
    CapybaraHelper.login 
    result = CapybaraHelper.access_and_fill_travel_page 
    assert_equal "/travels/success/#{Travel.last.uuid}", result[:final_path] 
    end 

end 

,这里是我在test/support/capybara/capybara_helper.rb创建的助手,以避免重复代码:

require 'test_helper' 
require 'capybara/rails' 
require 'capybara/poltergeist' 

module CapybaraHelper 
    def self.access_and_fill_travel_page options = {} 
    options.symbolize_keys! 
    set_js_driver 
    visit(Rails.application.routes.url_helpers.root_path) 
    initial_path = current_path 
    #Fields 
    fill_in('origin', with: options[:origin] || 'Guarulhos') 
    fill_autocomplete('origin', with: options[:origin] || 'Guarulhos') 
    fill_in('destination', with: options[:destination] || 'Seul') 
    fill_autocomplete('destination', with: options[:destination] || 'Seul') 
    fill_in('date_from', with: options[:date_from] || Date.today+10) 
    fill_in('date_to', with: options[:date_to] || Date.today+26) 
    fill_in('adults', with: options[:adults] || 1) 
    fill_in('children', with: options[:children] || 0) 
    fill_in('babies', with: options[:babies] || 0) 
    find('#travel-submit').click() 
    final_path = current_path 
    return {initial_path: initial_path, final_path: final_path} 
    end 

    def self.fill_autocomplete(field, options = {}) 
    page.execute_script %Q{ el = $('input[name=#{field}]').get(0) } 
    page.execute_script %Q{ $(el).trigger('focus') } 
    page.execute_script %Q{ $(el).trigger('keydown') } 
    page.all('.ui-menu-item', minimum: 1) 
    page.execute_script %Q{ item = $('.ui-menu-item').get(0) } 
    page.execute_script %Q{ $(item).trigger('mouseenter').click() } 
    end 

    def self.set_js_driver 
    Capybara.javascript_driver = :poltergeist 
    Capybara.current_driver = Capybara.javascript_driver 
    end 

    def self.login 
    user = FactoryGirl.create(:user) 
    login_as(user, :scope => :user) 
    end 

end 

回答

2

您应该使用ActionDispatch::IntegrationTest,而不是ActionController::TestCase作为父类使用水豚的测试。 ActionController::TestCase嘲笑了请求阶段和Rails的大部分。它在Rails 5中折旧。

不要调用测试帮助程序模块上的方法,而应将它们混合到测试类中。

class TravelsIntegrationTest < ActionDispatch::IntegrationTest 
    include Devise::Test::ControllerHelpers 
    include Warden::Test::Helpers 
    include CapybaraHelper 
    Warden.test_mode! 

    test 'should accept correct fields' do 
    login 
    # ... 
    end 
end 

module CapybaraHelper 
    def login(user = FactoryGirl.create(:user)) 
    login_as(user, scope: :user) 
    end 
end 

除此之外,而是缺乏在代码的组织 - 比如设置Warden.test_mode!设置步骤应该在你的test_helper.rb完成跨越你的测试不再重复。不要将所有的步骤定义放入单个文件中。例如,您可以将它们放在/test/support/中。

module SessionHelper 
    def login(user = FactoryGirl.create(:user)) 
    login_as(user, :scope => :user) 
    end 
end 

module TravelHelper 
    def access_and_fill_travel_page 
    # ... 
    end 
end 

如果你真的想要干的使用继承保持它设置你的测试类:

class BaseIntegrationTest < ActionDispatch::IntegrationTest 
    include Devise::Test::ControllerHelpers 
    include Warden::Test::Helpers 
    include SessionHelper 
end 

class TravelsIntegrationTest < BaseIntegrationTest 
    test 'should accept correct fields' do 
    login 
    # ... 
    end 
end 
+0

追随你的答案,我找到了原因,为什么有些方法是我的模块中不可访问,这是因为我使用类方法而不是实例方法。只要从方法声明中删除'self'和我称之为“CapybaraHelper”的方法解决了问题。 因为这个问题,我使用了'ActionController :: TestCase' https://github.com/plataformatec/devise/issues/3913,但是我没有注意到只是增加了'include Devise :: Test :: IntegrationHelpers'解决这个问题。 谢谢,我也创建了像你建议的新模块,它工作正常。 –

+0

并将'include SessionHelper'添加到'TravelSControllerTest'并不是单独工作。我还必须添加'require'support/session_helper'。 –

相关问题