ruby on rails - rails - ¿Por qué no usar conexiones compartidas de ActiveRecord para Rspec+Selenium?
rspec rails (6)
Parece que la forma más comúnmente aceptada de lidiar con Selenium y las pruebas es evitar el uso de dispositivos transaccionales y luego usar algo como database_cleaner entre pruebas / escenarios. Recientemente me encontré con el siguiente article que sugirió hacer lo siguiente:
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
Esto parece mucho mejor para el rendimiento que las alternativas. ¿Alguien tiene alguna razón por la cual esto no debería ser usado?
En realidad hay problemas con él. Si utiliza la gema mysql2, por ejemplo, comenzará a ver algunos errores como:
Mysql2::Error This connection is still waiting for a result
Por favor usa esto en su lugar. Fue escrito por Mike Perham, todos los créditos para él.
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
También necesitarás instalar gem connection_pool
. Esto le ahorrará muchos dolores de cabeza.
Esta solución fue escrita por José Valim, muy respetado en la comunidad de Rails y miembro del equipo central de Rails. Dudo que él recomendaría usarlo si hubiera problemas con él. Personalmente no he tenido ningún problema.
Solo tenga en cuenta que si utiliza Spork, esto debe estar en el bloque each_run para que funcione.
FWIW - He tenido problemas de prueba intermitentes de capibara con el parche anterior en Postgres. La solución de Mike Perham que tiene @hsgubert a continuación parece haber resuelto esos problemas. Ahora estoy usando esa solución.
Hay algo bueno al final de este post. Puede explicar por qué recibo un error MALLOC cuando intento una secuencia de comandos de subprocesos muy simple.
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)
He encontrado un problema con el código que mencionó en mi archivo spec_helper.rb.
¿Qué sucede cuando sus pruebas dependen del uso de conexiones a múltiples bases de datos? Tengo dos bases de datos a las que debo conectarme cuando ejecuto mis pruebas. Hice una prueba simple para verificar lo que estaba sucediendo con las conexiones de base de datos que establezco.
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>
Como puede ver, antes de llamar al método de conexión compartida, tengo dos conexiones de base de datos diferentes. Después, la llamada al método de conexión compartida, tengo solo uno.
Por lo tanto, cualquier prueba que requiera ir a la segunda conexión de base de datos para recuperar información fallará. :(
Voy a publicar este problema y ver si alguien ha llegado a una solución.
Solo estaba leyendo un poco sobre esto yo mismo. Descubrí el fragmento que compartiste aquí en esta publicación de blog:
Para responder a su pregunta directamente, la página de github del limpiador de la base de datos advierte que puede "dar como resultado fallas no deterministas". Seguiría adelante y lo usaría, pero si empiezas a encontrarte con errores extraños, tal vez este sea un buen lugar para comenzar a buscar.