Возникли проблемы с cache_classes / Spork после перехода на Capybara-Webkit из Selenium - PullRequest
1 голос
/ 28 февраля 2012

Некоторое время я использовал Selenium / Spork / Rspec, с cache_classes на false, и все, казалось, работало.

При переключении на webkit я начал получать ошибки, связанные с cache_classes (например, ожидаемый пользователь, получил User), поэтому я боролся с этим, чтобы попытаться установить для cache_classes значение true.

Однако, что бы я ни делал, я получаю следующую ошибку:

 Capybara::Driver::Webkit::WebkitInvalidResponseError:
   Unable to load URL: http://127.0.0.1:56398/login

Я пробовал все виды вещей ... в том числе:

Начинаю задумываться, стоит ли мне просто жить с cache_classes = false и выяснить, как избежать ошибок Factory Factory. Любая помощь будет оценена. Мой файл spork выглядит следующим образом:

require 'spork'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'

  require 'rspec/rails'
  require 'rspec/autorun'
  require 'capybara/rails'
  require 'capybara/rspec'
  require 'database_cleaner'
  require 'factory_girl'
  require 'authlogic/test_case'
  require 'email_spec'
  include Authlogic::TestCase

  require File.expand_path("../../config/environment", __FILE__)

  RSpec.configure do |config|
    # == Mock Framework
    #
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
    #
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr
    config.mock_with :rspec

    ApplicationController.skip_before_filter :activate_authlogic

    config.include(EmailSpec::Helpers)
    config.include(EmailSpec::Matchers)
    config.include Capybara::DSL

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
    #config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = false

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    config.before(:suite) do
      DatabaseCleaner.strategy = :truncation, {:except => %w[ages coefficients weights1 weights2 weights3 weights4 weights5 weights6 weights7 weights8 etfs]}
      DatabaseCleaner.clean
    end

    config.before(:each) do
      DatabaseCleaner.start
      Capybara.current_driver = :webkit if example.metadata[:js]
      #Capybara.current_driver = :selenium if example.metadata[:js]
      activate_authlogic
      ActiveRecord::Base.instantiate_observers
    end

    config.after(:each) do
      DatabaseCleaner.clean
      Capybara.use_default_driver if example.metadata[:js]
    end

    Capybara.default_selector = :css

  end

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  ## SUPPORT METHODS ##
  ## (erased for clarity) ##


  ## ##
  ActiveSupport::Dependencies.clear
end

Spork.each_run do
  #FactoryGirl.reload

  # Required to fix a recurring error when testing Active_Admin stuff
  # See here: http://railsgotchas.wordpress.com/2012/01/31/activeadmin-spork-and-the-infamous-undefined-local-variable-or-method-view_factory/
  # Delete at some point if active admin or whoever fixes this
  ActionView::Template.register_template_handler :arb, lambda { |template|
    "self.class.send :include, Arbre::Builder; @_helpers = self; self.extend ActiveAdmin::ViewHelpers; @__current_dom_element__ = Arbre::Context.new(assigns, self); begin; #{template.source}; end; current_dom_context"
  }

  #ActiveSupport::Dependencies.clear
end

ОБНОВЛЕНИЕ: Добавление примера спецификации на случай, если это поможет ....

describe "Items" do
  before(:each) do
    @user = Factory.create(:user)
    activate_authlogic
    b = # something not important
  end

  describe "usage paths" do

    it "the form directly from the basic_simulation show page should have correctly functioning javascript validation", :js => true do
      request_sign_in(@user) # This is a helper method which goes through the login form
      visit '/basic_simulation'
      fill_in "amount", :with => "-5000"
      click_button "Calculate"
      page.should have_selector("label.jquery-validator.amount-error", :text => "Please enter a value greater than or")
      fill_in "amount", :with => "5000"
      click_button "Calculate"
      page.should have_selector("input#amount", :value => "5000")
    end
end

1 Ответ

3 голосов
/ 28 февраля 2012

У вас проблемы с многопоточностью в Capybara-webkit и тестовом наборе.

Хосе Валим объясняет это гораздо яснее в недавнем сообщении в блоге.

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

Хитрость заключается в том, чтобы убедиться, что предложение Хосе находится в блоке Spork.each_run или оно не будет работать. Для наглядности вот соответствующие части моего spec_helper.rb.

require 'spork'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'capybara/rspec'

  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|

    config.mock_with :rspec

    config.fixture_path = "#{::Rails.root}/spec/fixtures"
    config.use_transactional_fixtures = true

    Capybara.default_driver     = :rack_test
    Capybara.default_selector   = :css
    Capybara.javascript_driver  = :webkit
  end
end

Spork.each_run do

  if Spork.using_spork?
    ActiveRecord::Base.instantiate_observers
  end

  require 'factory_girl_rails'

  # Forces all threads to share the same connection, works on Capybara because it starts the web server in a thread.
  class ActiveRecord::Base
    mattr_accessor :shared_connection
    @@shared_connection = nil

    def self.connection
      @@shared_connection || retrieve_connection
    end
  end

  ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
end

Несколько других небольших предложений:

  • Если вы используете последнюю версию factory_girl_rails, то вы следует использовать require factory_girl_rails в Spork.each_run блок и require factory_girl должны быть удалены из prefork
  • Последняя версия factory_girl_rails также больше не требует ActiveSupport::Dependencies.clear, хотя у некоторых людей все еще возникают проблемы без нее, поэтому вам следует протестировать ее удаление.
  • Я все еще не уверен насчет необходимости ActiveRecord::Base.instantiate_observers, но в любом случае он понадобится вам, только если вы используете наблюдателей, и я понимаю, что он должен быть в блоке each_run.

Попробуйте все это и посмотрите, работает ли оно для вас.

...