I'm struggling with this for quite a while now: I'm trying to upgrade an app from Rails 3.2 to Rails 4. While on Rails 3.2 all specs are passing, they fail under certain conditions in Rails 4.
Some specs are passing in isolation while failing when run together with other specs.
Example Video
https://www.wingolf.org/ak-internet-files/Spec_Behaviour.mp4 (4 mins)
This example video shows:
- Running 3 specs using
:focus
–––green. - Running them together with another spec–––two specs passing before now fail.
- Running the 3 specs, but inserting two empty lines–––one spec fails.
- Undo does not help when using guard.
- focus/unfocus does not help.
- Restarting guard does not help.
- Running all specs and then running the 3 specs again does help and make them green again. But adding the other task makes two specs fail, again.
As one can see, some specs are red when run together with other specs. Even entering blank lines can make a difference.
More Observations
- For some specs, passing or failing occurs randomly when run several times.
- The behavior is not specific to one development machine but can be reproduced on travis.
- To delete the database completely between the specs using database_cleaner does not help.
- To
Rails.cache.clear
between the specs does not help. - Wrapping each spec in an
ActiveRecord::Base.transaction
does not help. - This does occur in Rails 4.0.0 as well as in Rails 4.1.1.
- Using this minimal spec_helper.rb without spring or anything does not help.
- Using guard vs. using
bundle exec rspec some_spec.rb:123
directly doesn't make a difference. - This behavior goes for model specs, thus doesn't have to do anything with parallel database connections for features specs.
- I've already tried to keep as many gems at the same version as in the (green) Rails-3.2 branch, including guard, rspec, factory_girl, etc.–––does not help.
Update: Observations Based on Comments & Answers
Thanks to engineerDave, I've inserted
require 'pry'; binding.pry;
into one of the concerning specs. Using thecd
andshow-source
ofpry
, it was ingeniously easy and fun to narrow down the problem: Apparently, thishas_many :through
relation does not return objects when run together with other specs, even when called with(true)
.has_many(:groups, -> { where('dag_links.descendant_type' => 'User').uniq }, through: :memberships, source: :ancestor, source_type: 'Group' )
If I call
groups
directly, I get an empty result. But if I go through thememberships
, the correct groups are returned:@user.groups # => [] @user.groups(true) # => [] @user.memberships.collect { |m| m.group } # returns the correct groups
Has Rails changed the has many through behavior in Rails 4 in a way that could be responsible? (Remember: The spec works in isolation.)
Any help, insights and experiences are appreciated. Thanks very much in advance!
Code
- Current master branch on Rails 3.2––all green.
- Rails-4 branch––strange behavior.
- The file/commit seen in the video––strange behavior.
- All specs passing on travis for Rails 3.2.
- Diff of the
Gemfile.lock
(or usegit diff master..sf/rails4-minimal-update Gemfile.lock |grep rspec
)
How to Reproduce
This is how one can check if the issue still exists:
Preparation
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 the specs
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
The problem still exists, if the spec :213
is green in the second call but is red when run together with the other specs in the first call.