Почему бы не использовать общие подключения ActiveRecord для Rspec + Selenium? - PullRequest
46 голосов
/ 08 января 2012

Кажется, наиболее распространенный способ работы с 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

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

Ответы [ 6 ]

33 голосов
/ 23 августа 2012

На самом деле есть проблемы с ним. Например, если вы используете гем 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

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

15 голосов
/ 08 января 2012

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

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

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

2 голосов
/ 12 июля 2014

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

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

1 голос
/ 04 декабря 2013

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

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)
1 голос
/ 05 августа 2013

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

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

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

1 голос
/ 26 июля 2013

Я столкнулся с проблемой при использовании кода, который вы упомянули в моем файле 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>

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

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

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

...