-
-
Notifications
You must be signed in to change notification settings - Fork 757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nested Before/Around Run In Weird Order #2544
Comments
Verified this is a bit odd, we should at least document the order that we expect this to run in, I think at least around hooks should run after before when defined in an inner context |
So, I think this would be a good fix for RSpec 4? It's a bit odd, indeed! |
I'd like to give this a try, would you be willing to accept a PR for RSpec 4? |
Yes, for RSpec 4, I would recommend developing it as in an opt-in feature, and we will eventually need a way to warn about the change in behaviour. |
Sounds like a good plan to me! I'll see if I can find some time to work on it! |
Sometimes, the initial environment before the first spec would not be properly reset, causing some specs to fail if they run first. Reproducible with ``` bin/rspec \ --seed 52285 \ -e "Bundler.unbundled_env behaves like an unbundling helper should clean up RUBYLIB" ``` This change causes a separate spec failure, namely: ``` $ bin/rspec spec/bundler/gem_helper_spec.rb:294 1) Bundler::GemHelper gem management release:rubygem_push success messaging No allowed_push_host set RUBYGEMS_HOST env var is set should report successful push to the host from the environment Failure/Error: expect(Bundler.ui).to receive(:confirm).with(message) #<Bundler::UI::Shell:0x0000556bc98a8f60 @shell=#<Bundler::Thor::Shell::Color:0x0000556bc98e80e8 @base=nil, @mute=false, @padding=0, @always_force=false>, @Level="info", @warning_history=[]> received :confirm with unexpected arguments expected: ("Pushed lorem__ipsum 0.1.0 to https://custom.env.gemhost.com") got: ("Pushed lorem__ipsum 0.1.0 to rubygems.org") # ./spec/bundler/gem_helper_spec.rb:54:in `mock_confirm_message' # ./spec/bundler/gem_helper_spec.rb:286:in `block (6 levels) in <top (required)>' # ./spec/spec_helper.rb:100:in `block (2 levels) in <top (required)>' ``` This is due to some RSpec weirdness. In particular, rspec/rspec-core#2544. If you have an outer `before(:each)` block, and an inner `around(:each)` block, it turns out that the inner `around(:each)` runs before the outer `before(:each)`. This is very unintuitive and might change in future RSpec's. In our case, it causes a particular failure where the `around` hook would set a value for an environment variable, and then it would be unintentionally reset by our global `before` hook. We workaround the issue by changing the global `before` hook to an `around` hook, so that the ordering respects nesting.
Sometimes, the initial environment before the first spec would not be properly reset, causing some specs to fail if they run first. Reproducible with ``` bin/rspec \ --seed 52285 \ -e "Bundler.unbundled_env behaves like an unbundling helper should clean up RUBYLIB" ``` This change causes a separate spec failure, namely: ``` $ bin/rspec spec/bundler/gem_helper_spec.rb:294 1) Bundler::GemHelper gem management release:rubygem_push success messaging No allowed_push_host set RUBYGEMS_HOST env var is set should report successful push to the host from the environment Failure/Error: expect(Bundler.ui).to receive(:confirm).with(message) #<Bundler::UI::Shell:0x0000556bc98a8f60 @shell=#<Bundler::Thor::Shell::Color:0x0000556bc98e80e8 @base=nil, @mute=false, @padding=0, @always_force=false>, @Level="info", @warning_history=[]> received :confirm with unexpected arguments expected: ("Pushed lorem__ipsum 0.1.0 to https://custom.env.gemhost.com") got: ("Pushed lorem__ipsum 0.1.0 to rubygems.org") # ./spec/bundler/gem_helper_spec.rb:54:in `mock_confirm_message' # ./spec/bundler/gem_helper_spec.rb:286:in `block (6 levels) in <top (required)>' # ./spec/spec_helper.rb:100:in `block (2 levels) in <top (required)>' ``` This is due to some RSpec weirdness. In particular, rspec/rspec-core#2544. If you have an outer `before(:each)` block, and an inner `around(:each)` block, it turns out that the inner `around(:each)` runs before the outer `before(:each)`. This is very unintuitive and might change in future RSpec's. In our case, it causes a particular failure where the `around` hook would set a value for an environment variable, and then it would be unintentionally reset by our global `before` hook. We workaround the issue by changing the global `before` hook to an `around` hook, so that the ordering respects nesting.
Closing for now as there have been additional docs added, potential reorder can be looked at later. |
Subject of the issue
If you have a describe block with an before(:each) and then nest a describe block with an around(:each) the around(:each) runs before the before(:each). I would have thought the around(:each) is just a nice way of writing before(:each) after(:each) and sharing some state between them. but because of the way around(:each) always runs before before(:each) even if it is nested lower it makes around(:each) much less useful.
there doesn't seem to be a test case for this behaviour in the documentation so I'm not sure if this was deliberate or not. though, i guess it would be hard to change this behaviour because probably a lot of people rely on it.
https://relishapp.com/rspec/rspec-core/v/2-0/docs/hooks/around-hooks#before/after(:each)-hooks-are-wrapped-by-the-around-hook
Your environment
Steps to reproduce
actual:
expected:
here is how it works if they are both before(:each) rather than using an around(:each) for the inner.
The text was updated successfully, but these errors were encountered: