Проблема с капибарой: @request должен быть ActionDispatch::Request

У меня проблемы с работой Capybara с Rails. Просто тестирую эту якобы интересную тестовую штуку. Хорошо, в прикрепленном коде есть пара эквивалентных тестов. Первый сделан с использованием shoulda-context + Test::Unit, который поставляется вместе с Rails. Второй тест также проводится с помощью capybara и shoulda-context.

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

В то время как первый работает нормально, капибара выдает это сообщение об ошибке:

================================================================================
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

Есть ли у кого-нибудь решение? Должен ли я попробовать другую интеграционную структуру, такую ​​как 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)

Спасибо


person marcel massana    schedule 01.02.2012    source источник


Ответы (3)


Вы смешиваете типы тестов и пытаетесь утвердить шаблон в тесте неправильного типа. Вы должны утверждать шаблоны только в своих функциональных тестах, где вы просто напрямую тестируете контроллер, а не фактически имитируете взаимодействие с пользователем.

Capybara предназначена специально для интеграционного тестирования, которое, по сути, запускает тесты с точки зрения конечного пользователя, взаимодействующего с браузером. В этих тестах вы не должны утверждать шаблоны, потому что конечный пользователь не может так глубоко заглянуть в ваше приложение. Вместо этого вы должны проверять, что действие приводит вас на правильный путь.

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

См. раздел «DSL» в README Capybara на git: https://github.com/jnicklas/capybara

Официальное объяснение вашей проблемы: https://github.com/jnicklas/capybara/issues/240

person Ryan    schedule 02.02.2012
comment
Я пытался исправить это по вашим указаниям, но current_path.should == new_user_path не работает. Я думаю, что это RSpec, и я не использую RSpec. Кроме того, assert current_path, '\signup' не работает. Как я могу проверить current_path? - person marcel massana; 02.02.2012
comment
На самом деле, да, сопоставитель .should является частью RSpec. Моя ошибка. Однако предполагается, что current_path определяется как часть DSL, включенного в include Capybara::DSL. Когда вы пытаетесь использовать current_path, вы получаете ошибку «метод не определен» или что-то еще? - person Ryan; 03.02.2012
comment
Если бы я знал. Хотя я не считаю, что спецификации запросов должны проверять, какой шаблон был обработан, я также не знаю, почему они не могут этого сделать, основываясь на документах Rspec. Все, что я знаю, это то, что assert_template (которому делегирует render_template), кажется, работает только в спецификациях контроллера. Я всегда был в порядке с этим, потому что в моих спецификациях контроллера я проверяю шаблоны. - person Ryan; 25.09.2012


Спасибо за ваши советы @Ryan. Я пытался понять, как перевести некоторые примеры тестов интеграции RSpec с http://ruby.railstutorial.org/chapters/sign-up#sec:rspec_integration_tests в Test::Unit + Capybara. Первоначальный интеграционный тест RSpec был

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')

person marcel massana    schedule 02.02.2012
comment
При определенных условиях определенно возможно выполнить проверку того, что конкретный шаблон был обработан в рамках интеграционного теста. Я просто придерживаюсь мнения, что это неразумно. - person Ryan; 03.02.2012