【问题标题】:How can I clean my database between erroneous rspec specs?如何在错误的 rspec 规范之间清理我的数据库?
【发布时间】:2013-12-16 06:00:36
【问题描述】:

我已将 database_cleaner gem 添加到我的 rails 应用程序中,以便在规范之间清理我的数据库。这是我当前对 database_cleaner 的配置,位于spec/spec_helper.rb

  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.start
    DatabaseCleaner.clean
  end

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

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

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

现在,只要最后运行的每个规范都通过或失败,此配置就可以正常工作。

但是,如果发生错误(rspec 并没有像 minitest 那样给你一个漂亮的小E,它会抛出这样的事情:

09:17:32 - INFO - Running: spec
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/validations.rb:57:in `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)

),数据库没有被清理!错误之前的规范中的剩余数据保留在数据库中。我想这是因为 database_cleaner 没有将错误的规范视为完成,因此没有清理数据库。

现在,在您再次运行规范之前,这不会真正造成任何伤害。然后,残差数据会导致类似于以下的错误:

09:17:32 - INFO - Running: spec
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/validations.rb:57:in `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)

解决这个错误很简单;运行 rails_env=test rake db:reset 或启动数据库 shell 并使用 sql 语句清空相关表将清除这些数据并允许规范运行顺利。

但是,这越来越烦人了。我的任何规格中的一个错误字符(任何使它错误而不是失败的东西)都会导致我的整个测试工作流程阻塞,就像自动武器的发射机制一样!

您对 database_cleaner 有什么建议?您是否有任何示例配置允许清理数据库,即使在发生错误测试的情况下也是如此?

我正在使用 guard 来运行我的 rspecs,并通过 factory-girl 进一步增强:

宝石文件:

source 'https://rubygems.org'

group :development do
    gem 'capistrano'
    gem 'rb-fsevent'
    gem 'debugger'
end

group :development, :test do
    gem 'rspec-rails', '~> 2.14.0'
    gem 'sqlite3'
    gem 'guard-rspec'
    gem 'guard-livereload', require: false
    gem 'guard-shell'
    gem 'webrick', '~> 1.3.1'
end

group :test do
    gem 'factory_girl_rails'
    gem 'capybara', '~> 2.2.0'
    gem 'selenium-webdriver'
#   capybara-webkit gem requires an application called 'libqtwebkit-dev' to build. To install 'libqtwebkit-dev' in Ubuntu, run
#   sudo apt-get install libqtwebkit-dev
#   gem 'capybara-webkit'
    gem 'rb-readline'
    gem 'launchy'
    gem 'database_cleaner'
end

group :production do
    gem 'pg'
#   gem 'puma'
end

# rails version
gem 'rails', '4.0.1'

# standard library
gem 'sass-rails', '~> 4.0.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 1.2'


group :doc do
  gem 'sdoc', require: false
end

# custom 
gem 'activeadmin', github: 'gregbell/active_admin'
gem 'devise'
gem 'simple_form'

spec/spec_helper:

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'

# 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 }

# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

RSpec.configure do |config|
  config.include Capybara::DSL

  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.start
    DatabaseCleaner.clean
  end

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

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

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

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # config.include RSpec::Rails::RequestExampleGroup, type: :feature

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # 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"
end

【问题讨论】:

  • 你试过完全删除DatabaseCleaner吗? use_transactional_fixtures 行完全符合您的要求。
  • 我认为 use_transactional_fixtures 不适用于 rpsec,只有 rails 的集成测试套件。

标签: ruby-on-rails rspec factory-bot guard database-cleaner


【解决方案1】:

添加文件:

# RSpec
# spec/support/database_cleaner.rb
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end

并取消注释

Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

spec/rails_heper.rb

【讨论】:

    【解决方案2】:

    你想改变这个

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

    到这里:

    config.after(:suite) do
      DatabaseCleaner.clean_with(:truncation)
    end
    

    否则,它将简单地回滚事务,这将留下事务开始之前存在的所有数据。

    【讨论】:

    • 这应该是之前,而不是之后。
    【解决方案3】:

    请出示规格。

    您需要确保在 before/after/its 等语句中完成设置/拆卸。

    如果您在上述之外进行了设置和变量分配并且只是“在测试本身中”,那么测试将在您遇到的时候崩溃。如果在设置中完成,则可以避免此问题。

    您不应该像现在这样尝试对内部结构进行调整。与 Ror 领域的许多事情一样,如果您这样做,您的代码可能会“偏离”轨道。 Rails 旨在成为一个为您完成所有乏味工作的框架,您只需保持“在轨道上”。

    【讨论】:

      【解决方案4】:

      这对我有用:

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

      【讨论】:

      • 不适合我,虽然它没有我的配置那么冗长!这是因为数据不是在每个规范之前或在每个规范之后而是在每个规范期间写入数据库的。也许我应该考虑以不同的方式配置 rspec...
      • 在规范期间是测试通常写入数据库的时间。一定有其他问题。您是否打开了事务性装置?我没有,因为没有使用固定装置。
      猜你喜欢
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      相关资源
      最近更新 更多