0

このソリューションを使用して、javascript テスト中のデータベースの問題を回避しています。

スイートを最初に実行すると、テストは正常に実行され、すべて合格します。

スイート全体をもう一度実行しても、合格します。

しかし、個別のスペック ファイルを実行してからスイート (または他の個別のテスト) を実行しようとすると、次のエラーが発生します。

An error occurred in an after hook
  ActiveRecord::StatementInvalid: ArgumentError: prepare called on a closed database: rollback transaction
  occurred at /home/steveq/.rvm/gems/ruby-1.9.3-p194@rails32/gems/sqlite3-1.3.7/lib/sqlite3/database.rb:91:in `initialize'

1) Signing up with valid information
     Failure/Error: visit "/sign_up"
     ActiveRecord::StatementInvalid:
     ArgumentError: prepare called on a closed database: PRAGMA table_info("users")
 # ./app/controllers/registrations_controller.rb:3:in `new'
 # ./app/controllers/registrations_controller.rb:3:in `new'
 # ./spec/features/sign_up_feature_spec.rb:5:in `block (2 levels) in <top (required)>'

ガードをリロードすると、テストは再びパスします。

ここで何が起こっているのか、または考えられる解決策について何か洞察を持っている人はいますか? 考えられるすべてのバリエーションを試しました。ここに、試したことを示すspec_helperファイルがあります(バリエーションはコメントアウトされています。現在のコード-カピバラページで提案されているもの-現在使用しているものです) .

require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)


require 'rspec/rails'
  require 'rspec/autorun'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    #Make it so Selenium (out of thread) tests can work with transactional fixtures
    #REF http://opinionated-programmer.com/2011/02/capybara-and-selenium-with-rspec-and-rails-3/#comment-220
    # ActiveRecord::ConnectionAdapters::ConnectionPool.class_eval do
    #   def current_connection_id
    #     # Thread.current.object_id
    #     Thread.main.object_id
    #   end
    # end
    # FactoryGirl short syntax
    config.include FactoryGirl::Syntax::Methods

    config.use_transactional_fixtures = true

    # set up for use with :js => true. 
    # See http://stackoverflow.com/questions/8178120/capybara-with-js-true-causes-test-to-fail for more info 
    # config.before :suite do
    #   if Capybara.current_driver == :rack_test
    #     DatabaseCleaner.strategy = :transaction
    #   else
    #     DatabaseCleaner.strategy = :truncation
    #   end
    #   DatabaseCleaner.start
    # end

    # config.after do
    #   DatabaseCleaner.clean
    # end

    # standard RSPEC config
    # config.before(:suite)       :truncation
    #   else
    #     :transaction
    #   end do
    #   DatabaseCleaner.strategy = if example.metadata[:js]
    #     :truncation
    #   else
    #     :transaction
    #   end
    #   DatabaseCleaner.clean_with(:truncation)
    # end

    # config.before(:each) do
    #   DatabaseCleaner.start
    # end

    # config.after(:each) do
    #   DatabaseCleaner.clean
    # end

    # config.before(:each) do
    #   DatabaseCleaner.strategy = if example.metadata[:js]
    #     :truncation
    #   else
    #     :transaction
    #   end
    #   DatabaseCleaner.start
    # end

    # config.after(:each) do
    #   DatabaseCleaner.clean
    # end

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    # Run specs in random order to surface order dependencies. If you find an
    # order dependency and want to debug it, you can fix the order by providing
    # the seed, which is printed after each run.
    #     --seed 1234
    config.order = "random"

    config.treat_symbols_as_metadata_keys_with_true_values = true
    config.filter_run :focus => true
    config.run_all_when_everything_filtered = true

    config.include MailerMacros
    config.include LoginMacros
    config.before(:each) { reset_email }

    config.include Devise::TestHelpers, :type => :controller
    config.extend LoginMacros, :type => :controller
  end
end

Spork.each_run do
  # allows capybara JS tests to run in separate thread 
  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

  # This code will be run each time you run your specs.
  load "#{Rails.root}/config/routes.rb" 
  FactoryGirl.reload
  # reload all the models
  Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
    load model
  end


end
4

1 に答える 1

1

これが私が考え出したことです - 願わくば、この同じ問題に陥った他の誰かを助けることを願っています.

まず、私が使用していた方法:

Spork.each_run do
  # allows capybara JS tests to run in separate thread 
  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

  # This code will be run each time you run your specs.
  load "#{Rails.root}/config/routes.rb" 
  FactoryGirl.reload
  # reload all the models
  Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
    load model
  end


end

正常に動作しますが、sqlite では動作しないようです。

最も簡単な修正は、mysql のテスト データベースとして sqlite を交換することでした。それはすべてを解決しました。

もう 1 つの解決策は、私が現在掘り下げているもので、 spork を完全に削除してZeusを優先することでした。

github リンクからチェックアウトできますが、私が気に入っている理由を説明します。

必要な構成はありません。spec_helper に spork ブロックも、guardfile にも spork ブロックはありません。

また、サーバーとコンソールの初期化を 1 秒未満に高速化します。大したことではありませんが、非常に快適です。

私のテスト スイート (これまでに 191 の例) は、約 35 秒から 17.5 秒に短縮され、半分の時間になりました。

ぜひチェックしてみてください。

于 2013-03-28T20:03:30.717 に答える