Rails:minitest 是否使用 schema.rb 重新创建测试架构



我正在尝试使遗留的Rails系统达到更新的标准,但是在使测试数据库反映schema.rb的状态以及通过迁移所做的更改时遇到了问题。

运行rake minitest:all调用的代码与rake db:schema:load相同吗?

环境

  • 导轨 3.2.20
  • 红宝石 1.9.3
  • 迷你测试宝石 4.6.2
  • 最小测试轨 0.5.2
  • MySQL 5.1
  • 本地操作系统 X、测试和生产 Linux

原始系统状态

该系统最初是由非软件工程师、不了解 Rails 等的人建立的。 添加了几个特定于MySQL的类型(例如unsigned int(,这些类型在Rails的迁移和schema.rb中没有特别支持。 所以系统使用了structure.sql,并且对如何保持更新、签入 git 等等非常草率。

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

但是所有数百个测试(他们确实编写了很多测试(都是根据 id 而不是夹具名称编写的,并且夹具之间存在依赖关系等。 他们没有更新测试,而是决定坚持使用旧架构(带有数字id(进行测试,并使用新架构(在 id 中使用 varchar GUID(进行生产。

OP深吸一口气...

各种环境的数据库不同步,有数百个迁移,但它们停止工作,因为"开发"数据库是共享的,并且......你知道,这是一团糟。

我正在尝试解决所有这些问题,并最终迁移到PostgreSQL。

我做了什么

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

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

因此,我在本地将配置设置从:sql更改为使用:ruby设置来生成schema.rb

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

特别是,其中id字段是 GUID 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 => false防止迁移创建普通 ID
  • :force => false确保此迁移不会破坏生产数据库
  • 具有大小和其他类似主键设置的t.string "id"
  • 最后execute(ALTER TABLE ...)将 id 声明为主键

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

一旦生产、暂存、开发和其他数据库同步,那么一切都很好。

除非我们测试。

那么为什么当我运行 Minitest 时这不起作用?

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

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而不是varchar

如果我在运行 minitest 之前检查架构(在 dropcreate 和我的魔术迁移之后(,这是正确的:时髦的主键会根据需要varchar

但是在测试过程中的某个地方,模式似乎被改回了Rails标准。 我可以返回并检查 ID 列返回到int的架构。

据推测,该架构是从实际schema.rb生成的。

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

  • 迁移再次有效
  • 开发、测试、暂存、生产数据库在结构上是相同的
  • 我现在需要忍受疯狂varchar基于 GUID 的id字段
  • 如果可能的话,我宁愿不使用structure.sql

好的,所以我相信以下内容是正确的:迷你测试,或测试运行db:schema:load...或在RAILS_ENV=test中运行时db:structure:load - 这可以通过运行rake test --tracerake minitest:all --trace来观察。

因此,由于奇怪的使用varchar而不是int名为id的字段,我的schema.rb不会完全重新创建数据库......我不得不恢复使用structure.sql

解决方案的其余部分,包括将手动修改的schema.rb版本添加为第一次"汇总"迁移,效果很好,后续迁移也很好。 在未来的某个时候,我会将 id 变回它们的自然形式;目前,这是一个合适的解决方案,如果不是优雅的话。

相关内容

  • 没有找到相关文章

最新更新