【问题标题】:After upgrade to Rails 4: Specs fail in combination while passing in isolation升级到 Rails 4 后:Specs 组合失败,而单独通过
【发布时间】:2014-09-12 15:56:44
【问题描述】:

我为此苦苦挣扎了很长一段时间:我正在尝试an app 从 Rails 3.2 升级到 Rails 4。在 Rails 3.2 all specs are passing 上时,它们在 Rails 4 中的某些条件下会失败。

某些规范在与其他规范一起运行时会单独通过而失败

示例视频

https://www.wingolf.org/ak-internet-files/Spec_Behaviour.mp4(4 分钟)

此示例视频显示:

  1. 使用 :focus–––green 运行 3 个规范。
  2. 将它们与另一个规范一起运行——之前通过的两个规范现在失败了。
  3. 运行 3 个规范,但插入两个空行——一个规范失败。
    1. 使用保护时撤消没有帮助。
    2. 聚焦/不聚焦无济于事。
    3. 重新启动保护没有帮助。
    4. 运行所有规范,然后再次运行 3 个规范确实有助于使它们再次变绿。但是添加另一个任务又会导致两个规范失败。

正如我们所看到的,一些规格与其他规格一起运行时是红色的。即使输入空行也会有所作为。

更多观察

  • 对于某些规范,多次运行时通过或失败随机发生。
  • 该行为并非特定于一台开发机器,但可以在 travis 上重现。
  • 使用database_cleaner 在规范之间完全删除数据库没有帮助。
  • 在规范之间发送 Rails.cache.clear 无济于事。
  • Wrapping each spec in an ActiveRecord::Base.transaction 没有帮助。
  • Rails 4.0.0 和 Rails 4.1.1 中都会出现这种情况。
  • 在没有spring 的情况下使用this minimal spec_helper.rb 或任何东西都无济于事。
  • 使用guard 与直接使用bundle exec rspec some_spec.rb:123 没有区别。
  • 此行为适用于模型规范,因此不必对功能规范的并行数据库连接执行任何操作。
  • 我已经尝试将尽可能多的 gem 保留在与(绿色)Rails-3.2 分支中相同的版本,包括guard、rspec、factory_girl 等——但没有帮助。

更新:基于评论和答案的观察

  • Thanks to engineerDave,我已将require 'pry'; binding.pry; 插入到相关规格之一中。使用cd and show-source of pry,缩小问题范围非常简单有趣:显然,this has_many :through relation 与其他规范一起运行时不会返回对象,即使与(true) 一起调用也是如此。

    has_many(:groups,
      -> { where('dag_links.descendant_type' => 'User').uniq },
      through: :memberships,
      source: :ancestor, source_type: 'Group'
      )
    

    如果我直接调用groups,我会得到一个空结果。但如果我通过memberships,则返回正确的组:

    @user.groups                                #  => []
    @user.groups(true)                          #  => []
    @user.memberships.collect { |m| m.group }   # returns the correct groups
    

    Rails 是否以一种负责任的方式改变了 Rails 4 中的 has many through 行为?(请记住:该规范是独立工作的。)

感谢任何帮助、见解和经验。提前非常感谢!

代码

如何复制

这是检查问题是否仍然存在的方法:

准备

git clone git@github.com:fiedl/wingolfsplattform.git
cd wingolfsplattform
git checkout sf/rails4-minimal-update
bundle install
# please create `config/database.yml` to your needs.
bundle exec rake db:create db:migrate db:test:prepare

运行规范

bundle exec rspec ./vendor/engines/your_platform/spec/models/user_group_membership_spec.rb
bundle exec rspec ./vendor/engines/your_platform/spec/models/user_group_membership_spec.rb:213

如果规范 :213 在第二次调用中为绿色但在第一次调用中与其他规范一起运行时为红色,则问题仍然存在。

【问题讨论】:

  • 您没有在测试之间正确清理数据吗?
  • @sevenseacat,我试过 rspec 的 use_transactional_fixturesdatabase_cleanerwrapping each spec in a transaction manually。还有其他更好的方法吗?
  • 你确定你在测试环境中运行吗?
  • 测试的顺序是固定的,还是随机运行的?如果您在升级 Rails 的同时升级了 rspec 版本,这种行为可能会发生变化。
  • 我也怀疑这种奇怪的行为与您在规范中使用显式变量(例如@user)有关。我的猜测是变量从一个规范“泄漏”到另一个规范。我不使用显式变量,而是使用“let”语句,以确保值不会在规范之间泄漏。

标签: ruby-on-rails ruby-on-rails-4 rspec has-many-through


【解决方案1】:

基于您正在使用的:

  • 应该语法
  • 您表明您最近已升级(可能是捆绑更新?)
  • 您的失败消息表明 NilObject 错误。

可能是这样的原因吗?

https://stackoverflow.com/a/16427072/793330

您是否在测试中调用尚未实例化的对象?

我认为这可能是不推荐使用的 rspec 3 升级问题。

您是否排除了将 rspec gem 升级到新的 rspec 3 语法(2.99 或 3.0.0+)作为罪魁祸首?

"Remove support for deprecated expect(...).should. (Myron Marston)"

IMO 这种行为不会由 Rails 4 更新引起,因为它以您的测试套件为中心。

更新(使用 pry 调试):

您还可以使用pry gem 来了解您的规范中发生了什么。

基本上,您可以在规范执行之前放置一个大的“停止”标志(类似于调试中断),以便在该点获得对环境的处理。

it {
  require 'pry'; binding.pry
  should == something
}

虽然要注意有时这些 pry 调用会严重破坏警卫的线程,您必须使用 CTRL+Z 将其杀死,然后杀死显示的 -9 PID。

更新#2:查看更新的答案。

根据您的 has_many 问题,您可能会遇到 FactoryGirl 问题

您可能需要在 Factory 中触发 before 操作来预填充相关记录。虽然这可能会变得混乱,即这里是怪物,但您可以在您的工厂中触发之后和之前的回调,这将使这些对象成为现实。

after(:create) do |instance|
    do stuff here
end

【讨论】:

  • 谢谢,但我不确定这是否适用,因为我已经尝试将尽可能多的 gem 保留在与(绿色)Rails-3.2 分支中相同的版本,包括保护、rspec ,factory_girl等。问题仍然存在。我将准备另一个以最少的 gem 更新为证据的分支。
  • 如果你看一下this diff或者在本地输入git diff master..sf/rails4-minimal-update Gemfile.lock |grep rspec,你可以看到rspec还没有更新,仍然固定在rspec (2.14.1)This is the minimal-gem-update branch.
  • 你在使用 rvm 吗?您可能需要将 rvm gemset 清空,并确保没有使用不同版本的 rspec 来获取 ./bin 目录。还要在规范中添加一个 pry 调用“require 'pry'; binding.pry;”在失败的规范之前,查看对象是否存在或查看当时数据库的状态
  • 我们既不使用 rvm 也不使用 bin 存根。我们总是通过bundle exec。不存在 bin 目录。由于我们使用的是rbenv,所以我仔细检查了:rbenv rehash 没有解决问题。我马上试试你的pry 建议。
  • 感谢插入require 'pry'; binding.pry; 的提示。单独运行规范时,对象存在,与其他规范一起运行时,subjectnil。此外,输入主题定义返回nil。但我以前不知道撬棍。也许我会通过 pry 调试找到一些东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 2012-12-25
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
相关资源
最近更新 更多