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
これは、他の方法よりもパフォーマンスの点で負荷が高いようです。これを使用すべきでない理由はありますか?
このソリューションは、JoseValimによって作成されました。Railsコミュニティで高く評価されており、Railsコアチームのメンバーです。個人的には何の問題もありませんでした。
Sporkを使用する場合、これが機能するには、each_runブロックにある必要があることに注意してください。
FWIW-Postgresの上記のパッチで断続的なcapybaraテストの問題が発生しました。 @hsgubertが以下に持っているMikePerhamソリューションは、これらの問題を解決したようです。私は今そのソリューションを使用しています。
実際には問題があります。たとえば、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
もインストールする必要があります。これにより、多くの頭痛の種からあなたを救うことができます。
DatabaseCleaner gem readmeは、「なぜ」という質問に次のように答えます。
一般的なアプローチの1つは、すべてのプロセスに同じデータベース接続を使用させることです( 一般的なActiveRecordハック )が、このアプローチは非決定論的な失敗をもたらすことが報告されています。
Spec_helper.rbファイルに記載されているコードを使用して問題が発生しました。
テストが複数のデータベースへの接続の使用に依存している場合はどうなりますか?テストを実行するときに接続する必要のあるデータベースが2つあります。確立したデータベース接続に何が起こっているかを確認するために、簡単なテストを行いました。
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>
ご覧のとおり、共有接続メソッドを呼び出す前に、2つの異なるデータベース接続があります。共有接続メソッドを呼び出した後、1つしかありません。
したがって、情報を取得するために2番目のデータベース接続に移動する必要があるテストは失敗します。 :(
この問題を投稿して、誰かが解決策に到達したかどうかを確認します。
この投稿の最後に良いことがあります。非常に単純なスレッドスクリプトを実行しようとすると、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)
私はこれについて少し読んでいました。このブログ投稿であなたがここで共有したスニペットを発見しました:
http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/
あなたの質問に直接答えるために、 データベースクリーナーgithubページ は「非決定論的な失敗につながる」可能性があることを警告しています。私はすぐにそれを使用しますが、あなたが奇妙な失敗に遭遇し始めたら、多分これは探し始めるのに良い場所です。