1

我有一个功能/集成规范贯穿整个用户流程。在用户流程结束时,应用程序中的页面将显示Postgres数据库中的一些记录。当我自己运行测试时,它会通过。我可以看到它通过各种步骤正确保存,因为硒驱动程序打开Firefox:Capybara.current_driver = :selenium。然而,当它在一堆控制器规格之后运行时,这个规范几乎可以预料地失败。在这些控制器的规格,我做的唯一有趣的是运行此登录功能:使用DatabaseCleaner和事务进行快速测试。如何调试?

module DeviseMacros 
    def login_user 
    before(:each) do 
     @request.env['devise.mapping'] = Devise.mappings[:user] 
     user = create(:user_with_active_account) 
     sign_in user 
    end 
    end 
end 

所以我这样称呼它:

describe AwesomeController do 
    login_user 

    it 'responds with 200' do 
    get :new 
    expect(response.status).to eq 200 
    end 
end 

当控制器规范运行后我立刻就可以知道测试将失败,因为某些UI元素应该显示取决于数据库中的内容,显然它们不存在。

我DatabaseCleaner策略如下:

RSpec.configure do |config| 
    config.before(:suite) do 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:each) do 
    DatabaseCleaner.strategy = :transaction 
    end 

    config.before(:each, js: true) do 
    DatabaseCleaner.strategy = :truncation 
    end 

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

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

经过反复试验,我改变

config.before(:each) do 
    DatabaseCleaner.strategy = :transaction 
    end 

config.before(:each) do 
    DatabaseCleaner.strategy = :truncation 
    end 

而且沃拉,它传递。当然现在测试套件要花费两倍的时间。

我已经为了保证:truncation用于标记他们我所有的:selenium测试与js: true但其实并不重要,因为:selenium已经推动这些。但是,最重要的是,这些功能规格在这些控制器规格之后仍然失败。

我应该在哪里找?我如何继续调试?

唯一的其他独特的东西我在这里可能涉及的是:

# In spec/support/shared_db_connection.rb 
# https://gist.github.com/josevalim/470808 
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 

如何调试进行的任何意见或想法,将不胜感激。

如果您有任何其他问题,请询问。谢谢

更新:2016年6月1日

的导致失败的准确代码行是:

module DeviseMacros 
    def login_user 
    before(:each) do 
     @request.env['devise.mapping'] = Devise.mappings[:user] 
     user = create(:user_with_active_account) 
     sign_in user # <----- THIS GUY RIGHT HERE! When removed, the ControllerSpec fails but the integration test passes. 
    end 
    end 
end 

所以,出于某种原因,似乎击中DB与此控制器规范(使用:transaction策略)会影响功能规范(使用:truncation策略)。

我在辩论控制器规格时根本没有触及数据库,当试图认证一个设计用户,这对我来说很酷,但我觉得它不应该是那样的。如果我确实希望能够使用sign_in方法,有关如何继续的任何想法?

谢谢

+0

BTW,会发生什么时你到处使用“交易”策略?因为我认为这就是ActiveRecord补丁的意义所在,不是吗? – BoraMa

+0

@BoraMa感谢您的建议。当在任何地方使用':transaction'时,我会得到更多的错误,这些错误似乎与数据库相关。我更新了有关导致上述问题的代码行的更多信息。有任何想法吗? –

+0

好吧,我也会投票倾销这个AR补丁,并尝试在没有它的情况下解决问题。你可以发布你的'sign_in'方法吗?顺便说一句,我依稀记得我们在过去的测试中遇到过类似的问题。我们最终将测试分解为两个测试套件:所有非JS和所有JS,并且我们分别运行两个测试套件,而没有任何其他问题。 – BoraMa

回答

0

删除共享连接黑客,因为它会导致更多的问题比它的价值,并更新数据库清理配置来推荐一个从数据库清理自述 - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example

+0

我删除了shared_connection代码,并将database_cleaner规则更新为与链接完全相同。错误仍然发生。然而,我确实发现了导致错误的确切代码行,并更新了我上面的问题。这是否给你更多的想法? –

+0

解决方案需要检查所有功能规格并使用标签(:js)明确标记它们以确保它们全部使用“事务”。原来这些错误是从所有功能规格中随机发布的。只需咬一口子弹就可以使用较慢的功能规格。 –