Rails测试遗留数据库

时间:2014-01-28 10:55:41

标签: mysql ruby-on-rails

我有一个很大的问题。我已经开始将测试集成到我的rails应用程序中。它是现有数据库的管理系统。该应用程序运行良好,一切都已到位,但由于我决定使用rspec测试数据库搞砸了。

每当我运行:rake db:test:clone(我想克隆当前数据库以保存数据等)我得到一个mysql错误:

Invalid default value for 'active'

架构中有哪些:

t.string "active", limit: 0, default: "Yes", null: false

问题是limit:0。有大约50个字段对它们有limit:0,我很确定它们都是枚举/集合。解决这个问题的方法是什么?

2 个答案:

答案 0 :(得分:2)

为什么不能使用FactoryGirl

即使对于遗留数据库,您也必须能够使用Factory对模型建模,序列应该为您提供足够的唯一性,以便在规范运行时创建多个记录。如果你做不到,那么你遇到的问题比每次运行时重新创建测试数据库都要大,应该先解决。

您很可能尝试使用实际数据,因为您认为它最能代表数据中的随机性和真实性。但我怀疑它是否足以对您的代码进行压力测试。例如。你可以利用FFaker gem创建一个段落

Faker::Lorem.paragraph(1000)

这将测试数据库的文本字段。

# contrived factory example spec/factories/contrived_example_factory.rb
FactoryGirl.define do 
  factory :contrived_example do 
    description Faker::Lorem.paragraph(1000)
  end
end

现在您可以使用多个记录来锤击数据库,您可能会发现数据库无法处理它。最好在测试中找到这个而不是在生产中。

如果使用FactoryGirl的let语法,除非需要,否则不会创建。 (尽管请记住,使用let语法,let块中的东西在你实际调用它之前不存在。)一旦你设置了工厂,就可以使用#create_list

从工厂创建一个数据列表。
# In ContrivedExample Spec
let(:one_hundred_things) {FactoryGirl.create_list :your_factory_name_here, 100}

# And then Sample 1 item to use in your unit tests or integration tests. 
let(:one_thing) {one_hundred_things.sample)

# in unit test
it("saves") {expect(one_thing.save).to be_true}

# in integration test
it("#show") do                                                                                                                    
  get :show, id: one_thing.id                                                                                                        
  expect(assigns(:contrived_example)).to eq one_thing                                                                                           
end 

将此与Database Cleaner gem结合使用,您可以在每次测试后重新开始。将它与Spork结合使用,您将在测试中利用dRB,这样可以加快测试线程能力的附加好处。 :)

同样,@ xlembouras指出设置限制:0会将你的varchars设置为0.可能不是你想要实现的。

答案 1 :(得分:1)

我看待它的方式有两个问题需要解决。

首先,(恕我直言)最严重的是您需要一个完整的数据库来测试您的应用程序。这是以前错误的设计决策的严重迹象。

其次(在您的问题中更多)您的数据库中似乎存在不一致。
我可能会弄错,但我认为limit: 0是一个无效的选项。 (我认为字符串上的limit显示varchar的长度,但我对此没有信心。)

作为一种解决方法,您可以尝试使用rake db:test:prepare而不是克隆。