水豚问题:@request必须是ActionDispatch :: Request

时间:2012-02-01 23:22:00

标签: ruby-on-rails capybara shoulda testunit

我在让Capybara使用Rails时遇到问题。只测试那个有趣的测试用品。好的,在附加的代码中有几个等价的测试。第一个是使用Rails附带的shoulda-context + Test :: Unit。第二次测试也是用水豚和上下文进行的。

require 'integration_test_helper'

class UsersTest < ActionDispatch::IntegrationTest
  fixtures :all

  context "signup" do

    context "failure" do

      setup do
      @attr = { :name => "", :email => "", :password => "", :password_confirmation => "" }
      end

      should "not make a new user" do
        assert_no_difference 'User.count' do
          post_via_redirect "users", :user =>@attr  # enviem les dades d'un nou usuari via create (POST /users)
          assert_template 'users/new'     # ens retorna a users/new, que significa que no s'ha creat l'usuari
          assert_select "div#error_explanation" # comprovem que conte missatges d'error
        end
      end

      should "not make a new user (capybara)" do
        assert_no_difference 'User.count' do
          visit '/signup'
          fill_in 'Name', :with => @attr[:name]
          fill_in 'Email', :with => @attr[:email]
          fill_in 'Password', :with => @attr[:password]
          fill_in 'Confirmation', :with => @attr[:password_confirmation]
          click_button 'Sign Up!'
          assert_template 'users/new'     # ens retorna a users/new, que significa que no s'ha creat l'usuari
          assert_select "div#error_explanation" # comprovem que conte missatges d'error
        end
      end
    end
end

当第一个工作正常时,capybara会抛出此错误消息:

================================================================================
Error:
test: signup failure should not make a new user (capybara). (UsersTest):
ArgumentError: @request must be an ActionDispatch::Request
    test/integration/users_test.rb:30:in `block (4 levels) in <class:UsersTest>'
    test/integration/users_test.rb:23:in `block (3 levels) in <class:UsersTest>'
================================================================================

所需的* integration_test_helper.rb *文件是我发现的所有可用解决方案的累加器,并且对我不起作用。

require 'test_helper'
require 'capybara/rails'
require 'database_cleaner'

# Transactional fixtures do not work with Selenium tests, because Capybara
# uses a separate server thread, which the transactions would be hidden
# from. We hence use DatabaseCleaner to truncate our test database.
DatabaseCleaner.strategy = :truncation

class ActionDispatch::IntegrationTest
  # Make the Capybara DSL available in all integration tests
  include Capybara::DSL

  # Stop ActiveRecord from wrapping tests in transactions
  self.use_transactional_fixtures = false

  teardown do
    DatabaseCleaner.clean       # Truncate the database
    Capybara.reset_sessions!    # Forget the (simulated) browser state
    Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
  end
end

有人有解决方案吗?我应该尝试另一个整合frmawork,如webrat?

我的设置是:

marcel@pua:~/Desenvolupament/Rails3Examples/ror_tutorial$ rake about
About your application's environment
Ruby version              1.9.2 (x86_64-linux)
RubyGems version          1.8.15
Rack version              1.3
Rails version             3.1.3
JavaScript Runtime        therubyracer (V8)
Active Record version     3.1.3
Action Pack version       3.1.3
Active Resource version   3.1.3
Action Mailer version     3.1.3
Active Support version    3.1.3
Middleware                ActionDispatch::Static, Rack::Lock, #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000002b9bac0>, Rack::Runtime, Rack::MethodOverride, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::RemoteIp, Rack::Sendfile, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, ActionDispatch::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport
Application root          /mnt/dropbox/Dropbox/DESENVOLUPAMENT/Rails3Examples/ror_tutorial
Environment               development
Database adapter          sqlite3
Database schema version   20120127011330

另外

shoulda-context (1.0.0)
capybara (1.1.2)

由于

3 个答案:

答案 0 :(得分:11)

您正在混合测试类型并尝试在错误类型的测试中断言模板。您应该只在功能测试中断言模板,在那里您只是直接测试控制器而不是实际模拟用户交互。

Capybara专门用于集成测试,它实质上是从最终用户与浏览器交互的角度运行测试。在这些测试中,您不应该断言模板,因为最终用户无法深入了解您的应用程序。你应该测试的是,一个动作会让你走上正确的道路。

current_path.should == new_user_path
page.should have_selector('div#error_explanation')

请参阅Capybara的README中的“DSL”部分git:https://github.com/jnicklas/capybara

您的问题的官方解释:https://github.com/jnicklas/capybara/issues/240

答案 1 :(得分:1)

为了我的完整性,因为我知道我会一遍又一遍地回到这个链接:

使用测试单元和水豚的人也是一个很好的入门书:from techiferous

请注意使用assert page.has_content?("something")

这与使用assert_equal some_path, current_path测试路线一样好。

它是最完整的,不知道,但你不需要更多。

答案 2 :(得分:0)

感谢您的提示@Ryan。我试图弄清楚如何将http://ruby.railstutorial.org/chapters/sign-up#sec:rspec_integration_tests中的一些RSpec Integration测试示例转换为Test :: Unit + Capybara。最初的RSpec Integration测试是

it "should not make a new user" do
  lambda do
      visit signup_path
      fill_in "Name",         :with => ""
      fill_in "Email",        :with => ""
      fill_in "Password",     :with => ""
      fill_in "Confirmation", :with => ""
      click_button
      response.should render_template('users/new')
      response.should have_selector("div#error_explanation")
    end.should_not change(User, :count)
  end
end

因此,在您回答之后,我说原始示例不应包含response.should render_template('users/new')