Rails:minitest是否使用schema.rb重新创建测试模式?

时间:2015-04-09 19:42:32

标签: mysql ruby-on-rails ruby ruby-on-rails-3 rails-migrations

我正在尝试为传统的Rails系统提供更多当前标准,但是在测试数据库反映通过迁移进行的schema.rb 加上更改的状态时遇到了问题。

tl; dr 运行rake minitest:all是否会调用与rake db:schema:load相同的代码?

环境

  • Rails 3.2.20
  • Ruby 1.9.3
  • Minitest gem 4.6.2
  • minitest-rails 0.5.2
  • MySQL 5.1
  • 本地OS X,测试和生产Linux

原始系统状态

该系统最初是由非软件工程师,不了解Rails等人设置的。添加了几种特定于MySQL的类型(例如unsigned int),这些类型并不是使用Rails& #39;迁移和schema.rb。因此,系统使用了structure.sql,并且对于如何更新,检入git等等非常草率。

此外,稍后某人决定替换一些常用的数字,自动递增主键id字段,其中varchar包含自生成GUID。字段名称仍为id,但它是一种新的数据类型。

但是所有数百个测试(他们做了编写了大量测试)都是基于id而不是夹具名称写入参考夹具实例,而且夹具等之间存在依赖关系。与更新测试相比,他们决定坚持使用旧模式(使用数字id)进行测试,并使用新模式(使用id中的varchar GUID)进行生产。

OP深呼吸......

各种环境的数据库不同步,有数百次迁移,但由于"开发"数据库被共享了......嗯,你知道,这是一团糟。

我正在尝试修复所有这些,并最终转移到PostgreSQL。

我做了什么

我使用RAILS_ENV=production rake db:structure:dump从本地生产数据库中转储了架构 - 这产生了一个权威的structure.sql。我创建了一个新的开发数据库,​​并使用rake db:structure:load加载了它的模式 - 我仔细比较了生产和开发模式,它们是相同的,甚至是我上面提到的特定于MySQL的unsigned int。

我想转而使用schema.rb有两个原因。首先,我想进入一个不依赖于MySQL的系统。其次,当使用structure.sql时,我们检查一个文件,该文件具有自动增量值,数据库设置和任何机器的其他特征,它们运行最新的db:migrate。这可能会产生我宁愿避免的问题。

因此,我在本地更改了:sql的配置设置,以使用:ruby设置生成schema.rb

但是schema.rb真的不喜欢将id字段转换为varchar的想法 - 我确保所有使用此字段的模型都声明{ {1}},然后我创建了一个新的迁移来替换所有旧的迁移,"汇总迁移",其内容主要是新的self.primary_key = :id,但在几个方面进行了修改。

特别是,schema.rb字段是GUID id,我设置了这样的表(从迁移中):

varchar

所以:

  • class RolledUpStateAsOf20150403 < ActiveRecord::Migration def up # ... all other table definitions in the system create_table "users", :id => false, :force => false do |t| t.string "id", :limit => 36, :default => "", :null => false t.string "login" # and all the other user fields end execute("ALTER TABLE users ADD PRIMARY KEY (id);") #... end def down raise ActiveRecord::IrreversibleMigration end end 阻止迁移创建正常ID
  • :id => false以确保此迁移不会对生产数据库进行核对
  • :force => false包含大小和其他类似主键的设置
  • 最后
  • t.string "id"将id声明为主键

每次我在将来创建新的迁移时,execute(ALTER TABLE ...)都会更新 - 它现在不会准确(直到我们以后删除那些古怪的schema.rb字段) 。迁移将尊重正常的Rails实践。

一旦生产,登台,开发和其他数据库同步,那么一切都很顺利。

除非我们测试。

那么,为什么我在运行Minitest时没有工作?

我正在使用minitest运行测试,如下所示:

id

然后我开始看到错误,错误是由于RAILS_ENV=test rake db:drop RAILS_ENV=test rake db:create RAILS_ENV=test rake db:migrate RAILS_ENV=test rake minitest:all 列被定义为id而不是int

如果我在运行minitest之前检查架构 (在varchardrop之后,以及我的神奇迁移),那么它是正确的:时髦的主键是{{1根据需要。

但是在测试期间的某个地方看起来模式正在变回Rails标准。我可以返回并检查ID列返回到create的架构。

据推测,架构是从实际的varchar生成的。

这是正常/预期的行为吗?关于如何实现我的目标的任何建议,简单地说:

  • 迁移再次工作
  • 开发,测试,升级,生产数据库在结构上是相同的
  • 我现在需要使用疯狂的int基于GUID的schema.rb字段
  • 首选如果可能,不要使用varchar

1 个答案:

答案 0 :(得分:2)

好的,所以我相信以下是真的:minitest,或者测试db:schema:load中运行时运行db:structure:load ...或RAILS_ENV=test - - 通过运行rake test --tracerake minitest:all --trace可以观察到这一点。

所以,因为我schema.rb无法完全重新创建数据库,因为名为varchar的字段奇怪地使用了int而不是id ...我有恢复使用structure.sql代替。

解决方案的其余部分,包括添加手动修改版本的schema.rb作为第一个&#34;汇总&#34;迁移工作得很好,随后的迁移也很好。将来的某个时候,我会将ids变回自然形态;就目前而言,如果不是优雅的话,这是一个合适的解决方案。