升级到Rails 4后:Specs在隔离传递时组合失败

fie*_*edl 9 rspec ruby-on-rails has-many-through ruby-on-rails-4

我现在已经挣扎了很长一段时间了:我正在尝试应用程序从Rails 3.2 升级到Rails 4.虽然在Rails 3.2上所有规格都在通过,但它们在Rails 4中的某些条件下会失败.

有些规格在与其他规格一起运行时失败而且孤立的.

示例视频

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

此示例视频显示:

  1. 使用:focus---绿色运行3个规格.
  2. 将它们与另一个规格一起运行 - 之前传递的两个规格现在失败了.
  3. 运行3个规格,但插入两个空行 - 一个规格失败.
    1. 使用后卫时,撤消无效.
    2. 焦点/焦点没有帮助.
    3. 重启后卫没有帮助.
    4. 运行所有规格,然后再次运行3规格确实有帮助,并使它们再次变绿.但是,添加其他任务再次导致两个规格失败.

可以看出,当与其他规格一起运行时,某些规格是红色的.即使输入空行也可以有所作为.

更多观察

  • 对于某些规范,运行多次时会随机发生传递或失败.
  • 该行为不是特定于一台开发机器,而是可以在travis上重现.
  • 使用database_cleaner在规范之间完全删除数据库没有帮助.
  • Rails.cache.clear的规格之间并没有帮助.
  • 将每个规格包装在一个ActiveRecord::Base.transaction没有帮助.
  • 这确实发生在Rails 4.0.0以及Rails 4.1.1中.
  • 使用这个最小的spec_helper.rb没有弹簧或任何东西都无济于事.
  • 直接使用后卫与使用bundle exec rspec some_spec.rb:123并没有什么区别.
  • 此行为适用于模型规范,因此不必对功能规范的并行数据库连接执行任何操作.
  • 我已经尝试在与(绿色)Rails-3.2分支相同的版本中保留尽可能多的宝石,包括guard,rspec,factory_girl等.---没有帮助.

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

  • 感谢engineerDave,我已插入require 'pry'; binding.pry;其中一个相关规范.使用cdshow-source之后pry,缩小问题非常容易和有趣:显然,当与其他规范一起运行时,这种has_many :through关系不返回对象,即使在调用时也是如此(true).

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

    如果我groups直接打电话,我会得到一个空的结果.但是,如果我通过memberships,则返回正确的组:

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

    有没有Rails以一种可能负责的方式改变了Rails 4中的许多行为?(请记住:规范是孤立的.)

任何帮助,见解和经验都表示赞赏.首先十分感谢!

如何再现

这是人们可以检查问题是否仍然存在的方式:

制备

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
Run Code Online (Sandbox Code Playgroud)

运行规范

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
Run Code Online (Sandbox Code Playgroud)

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

eng*_*ave 5

基于您正在使用的:

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

这样的事可能是什么导致了它?

/sf/answers/1149895071/

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

我认为这可能是一个rspec 3升级问题,应该弃用.

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

"删除对弃用期望的支持(...).应该.(Myron Marston)"

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

更新(使用pry调试):

您还可以使用pry gem来查看规范中的内容.

实际上,您可以在规范执行之前设置一个大的"停止"符号(类似于调试中断),以便在此时获取环境句柄.

it {
  require 'pry'; binding.pry
  should == something
}
Run Code Online (Sandbox Code Playgroud)

虽然beaware有时候这些pry会在后卫的线程上破坏破坏,你必须用CTRL + Z杀死它,然后杀死显示的-9 PID.

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

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

您可能需要在Factory中触发before操作以预先填充关联的记录.虽然这可能会变得混乱,即这里是怪物,但是你可以在你的工厂回调之前和之后触发这些对象.

after(:create) do |instance|
    do stuff here
end
Run Code Online (Sandbox Code Playgroud)