2013-03-22 104 views
0

我使用this solution以避免javascript测试期间的数据库问题。Rspec,后卫,spork和水豚/硒 - 配置为js测试

通过套件中的第一次运行,测试运行正常,所有路过。

如果我再次运行整个套件,他们还是会通过。

但是,如果我运行一个单独的规范文件,然后尝试运行套件(或其他单个测试),我得到这个错误:

An error occurred in an after hook 
    ActiveRecord::StatementInvalid: ArgumentError: prepare called on a closed database: rollback transaction 
    occurred at /home/steveq/.rvm/gems/[email protected]/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 
+0

你如何创建用户登录? – 2013-03-22 23:02:07

+0

用户使用FactoryGirl创建。 – Squadrons 2013-03-25 19:59:59

回答

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的。

最快的解决方法是简单地将sqlite换成mysql的测试数据库。这解决了一切。

另一个解决方案,我现在真的在挖掘,就是完全放弃spork来支持Zeus

你可以通过github链接查看,但我会告诉你为什么我喜欢它。

它没有必要的配置 - 在spec_helper中没有spork块,在guardfile中没有spork块。

这也加快了服务器和控制台初始化到第二个 - 不是很大的交易,但非常,非常愉快。

我的测试套件(目前为止有191个示例)从运行时间大约35秒到17.5秒 - 一半时间。

我强烈建议你检查出来。