在同时测试中设计测试数据库记录冲突

时间:2012-12-31 10:55:27

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

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

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

users调用中删除所有after(:all) { User.delete_all }后,使用bundle exec rspec spec --order default

按顺序运行时,所有测试都会通过

如果users中未删除所有after(:all) { User.delete_all },则会在运行测试时显示电子邮件唯一性错误。设计错误来验证每个用户的电子邮件的唯一性,所以我认为第二次运行测试时,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引擎

1 个答案:

答案 0 :(得分:3)

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

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

希望它有所帮助!