Подтвердить что ты не робот

Почему бы не использовать общие соединения ActiveRecord для Rspec + Selenium?

Кажется, что наиболее распространенным способом борьбы с Selenium и тестов является избежание использования транзакционных приборов, а затем использование чего-то типа database_cleaner между тестами/сценариями. Недавно я столкнулся с следующей статьей которая предложила сделать следующее:

spec_helper.rb

class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil

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

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

Это кажется более загруженным для производительности, чем альтернативы. У кого-нибудь есть причина, почему это не должно использоваться?

4b9b3361

Ответ 1

Это решение было написано Хосе Валимом - очень уважаемым в сообществе Rails и членом основной команды Rails. Я сомневаюсь, что он порекомендовал бы использовать его, если бы были проблемы с ним. У меня лично не было никаких проблем.

Просто имейте в виду, что если вы используете Spork, это должно быть в блоке each_run для работы.

FWIW. У меня были проблемы с прерывистым выпуском capybara с вышеупомянутым патчем на Postgres. Решение Майка Перхама, которое @hsgubert ниже, похоже, решило эти проблемы. Теперь я использую это решение.

Ответ 2

На самом деле есть проблемы с ним. Например, если вы используете gem mysql2, вы увидите некоторые ошибки, например:

Mysql2::Error This connection is still waiting for a result

Пожалуйста, используйте это вместо этого. Это было написано Майком Перхамом, все его кредиты.

class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil

  def self.connection
    @@shared_connection || ConnectionPool::Wrapper.new(:size => 1) { retrieve_connection }
  end
end

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

Вам также потребуется установить gem connection_pool. Это избавит вас от многих головных болей.

Ответ 3

DatabaseCleaner gem readme отвечает на ваш вопрос "почему нет" таким образом:

Один общий подход заключается в том, чтобы заставить все процессы использовать одно и то же соединение с базой данных (общий взлом ActiveRecord), однако, как сообщается, этот подход приводит к не детерминированные отказы.

Ответ 4

Я столкнулся с проблемой, используя код, упомянутый в моем файле spec_helper.rb.

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

class ActiveRecord::Base
   mattr_accessor :shared_connection
   @@shared_connection = nil

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

# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
puts "First Record cxn: #{FirstDatabase::Record.connection}"
# => First Record cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xe59b524>
puts "AR Base cxn: #{ActiveRecord::Base.connection}"
# => AR Base cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xc52761c>
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

puts "First Record cxn: #{FirstDatabase::Record.connection}"
# => First Record cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xc52761c>
puts "AR Base cxn: #{ActiveRecord::Base.connection}"
# => AR Base cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xc52761c>

Как вы можете видеть, до того, как я вызову метод общего подключения, у меня есть два разных подключения к базе данных. После вызова метода общего подключения у меня есть только один.

Таким образом, любой тест, требующий перехода ко второму соединению базы данных для извлечения информации, не удастся.: (

Я собираюсь опубликовать эту проблему и посмотреть, пришел ли кто-нибудь к решению.

Ответ 5

Я просто немного читал об этом. Я обнаружил фрагмент, который вы поделили здесь в этом сообщении в блоге:

http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/

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

Ответ 6

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

http://apidock.com/rails/ActiveRecord/Base/connection

leente - March 15, 2011 0 thanks
Don't cache it!

Don’t store a connection in a variable, because another thread might try to use it when it’s already checked back in into the connection pool. See: ActiveRecord::ConnectionAdapters::ConnectionPool

connection = ActiveRecord::Base.connection

threads = (1..100).map do
  Thread.new do
    begin
      10.times do
        connection.execute("SELECT SLEEP(1)")  # WRONG
        ActiveRecord::Base.connection.execute("SELECT SLEEP(1)")  # CORRECT
      end
      puts "success"
    rescue => e
      puts e.message
    end
  end
end

threads.each(&:join)