rails ruby-on-rails ruby rspec capybara

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?


El gem léame de DatabaseCleaner gem responde a su pregunta de "por qué no" de esta manera:

Un enfoque común es forzar a todos los procesos a utilizar la misma conexión de base de datos ( article ), sin embargo, se ha informado que este enfoque da como resultado fallas no deterministas.


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:

article

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.