使用DatabaseCleaner和事务进行的片状测试。如何调试?

时间:2016-06-01 05:41:52

标签: ruby-on-rails selenium devise capybara-webkit database-cleaner

我有一个贯穿整个用户流的功能/集成规范。在该用户流程结束时,应用程序中的页面将显示Postgres数据库中的一些记录。当我自己运行测试时,它会通过。我可以通过各种步骤看到它正确保存,因为selenium驱动程序打开了firefox:Capybara.current_driver = :selenium。但是,当它在一堆控制器规范之后运行时,这个规范几乎可以预见地失败。在那些控制器规范中,我正在做的唯一有趣的事情就是运行这个登录功能:

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

瓦拉,它过去了。当然,现在测试套件的使用时间超过2倍。

我已使用:selenium标记了所有js: true次测试,以确保:truncation用于他们,但这并不重要,因为: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

因此,出于某种原因,使用此控制器规范(使用:transaction策略)点击数据库会影响功能规范(使用:truncation策略)。

我正在辩论在尝试验证设备用户时,根本没有在控制器规范中点击DB,这对我来说很酷,但我觉得它不应该那样。如果我确实希望能够使用sign_in方法,有关如何继续的任何想法吗?

谢谢

1 个答案:

答案 0 :(得分:0)

删除共享连接hack,因为它会导致更多问题,并将数据库清理程序配置更新为数据库清理程序README中推荐的配置 - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example