Почему бы не использовать общие соединения 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
Это кажется более загруженным для производительности, чем альтернативы. У кого-нибудь есть причина, почему это не должно использоваться?
Ответы
Ответ 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)