【问题标题】:Devise test database records conflicts on simultaneous tests设计测试数据库记录同时测试的冲突
【发布时间】:2012-12-31 10:55:26
【问题描述】:

我从以下工厂生成用户、客户和发票

FactoryGirl.define do
  factory :user do
    sequence(:email) { |n| "person_#{n}@example.com" }
    password "foobar"
    password_confirmation "foobar"
  end

  factory :client do
    sequence(:name) { |n| "Client Name #{n}" }
    sequence(:address1) { |n| "#{n} Street name" }
    sequence(:address2) { |n| "#{n} Area name" }
    city "Chennai"
    state "Tamil Nadu"
    country "India"
    zipcode "600001"
    contactname "Sathish Manohar"
    sequence(:email) { |n| "person_#{n}@example.com"}
    user
  end

  factory :invoice do
    client
  end
end

我有一些要求和型号规格,以下是我的主要要求规格:

https://gist.github.com/4418869 - clients_pages_spec.rb
https://gist.github.com/4418876 - invoices_pages_spec.rb

当在after(:all) { User.delete_all } 调用中删除所有users 时,所有测试在使用bundle exec rspec spec --order default 按顺序运行时都会通过

after(:all) { User.delete_all } 中的所有users 未被删除时,运行测试时会出现电子邮件唯一性错误。这是设计验证每个用户电子邮件的唯一性的错误,所以我认为在第二次运行测试时,factory_girl 尝试创建相同的用户。

这是错误信息:
/home/sathish/.rvm/gems/ruby-1.9.3-p194@invoice_jet/gems/activerecord-3.2.8/lib/active_record/validations.rb:56:in `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)

如何消除此错误消息,并创建设计用户以进行正确的测试?

背景信息:
spec_helper.rbconfig.use_transactional_fixtures = true
使用mysql作为数据库所有表都使用InnoDB引擎

【问题讨论】:

    标签: ruby-on-rails devise tdd factory-bot rspec-rails


    【解决方案1】:

    我认为您应该在每个规范之后定义一个完全清理数据库的默认策略,并通过这样做来保证每个测试的隔离。

    查看https://github.com/bmabey/database_cleaner 上的 Database Cleaner gem。

    您所要做的就是将 gem 放入您的 Gemfile,运行 bundle(假设您正在使用 bundler)并定义一个策略,如下所示:

    RSpec.configure do |config|
    
      config.before(:suite) do
        DatabaseCleaner.strategy = :transaction
        DatabaseCleaner.clean_with(:truncation)
      end
    
      config.before(:each) do
        DatabaseCleaner.start
      end
    
      config.after(:each) do
        DatabaseCleaner.clean
      end
    
    end
    

    希望对你有帮助!

    【讨论】:

    • 我同意,测试绝对应该被隔离,但根据我的经验,最好在每次测试之前清理数据库,而不是之后。这样,当出现故障时,您可以查看数据库,然后查看有问题的数据。
    • 由于数据库只是您数据的存储机制,我不太同意您的说法...您的对象模型是您的应用程序,您的数据库只是为您提供了一种保持此类状态的方法通过持久化对象。无论如何,希望 DB Cleaner Gem 可以帮助您解决所描述的问题
    • 我不是问这个问题的人。我同意数据库只是数据的存储,但代码中的数据库层也可能是错误的来源,查看实际存储的数据可能很有用。因此,我认为在每次测试之前清理数据库是一种做法,而不是之后。与每次测试后清洁相比,您认为有哪些缺点?
    • 对不起,没注意到……我完全没有看到任何缺点,我只是在争论原因。
    • 谢谢!您的回答连同这篇文章 (devblog.avdi.org/2012/08/31/…) 帮助我解决了这个问题。看来我也需要设置config.use_transactional_fixtures = false
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多