Skip to content
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

Warn if a fixture method is called from a before(:context) block. #1501

Merged
merged 2 commits into from
Dec 15, 2015

Conversation

fables-tales
Copy link
Member

Fixes #1442.

The basic approach here is to capture the addition of the fixture
methods to the example group instance and then monkeypatch them. The
monkeypatch checks to see if we're currently in a before(:context) hook
and if we are then it prints a warning and doesn't invoke the method.

The warning here is a little sparse at the moment, and I'd like to make
it more clear. One thing that's a little gross about this implementation
is that it uses the inspect string of the example group to determine if
we're in a before(:context) hook. As far as I can tell there isn't a
better way to make that determination, but maybe someone's got a clever
trick.

def self.proxy_method_warning_if_called_in_before_context_scope(method_name)
orig_implementation = instance_method(method_name)
define_method(method_name) do |*args, &blk|
if self.inspect.include?("before(:context)")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really the only way to detect this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not think of a better one after staring at the source... maybe @myronmarston has thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is pretty gross and brittle. Also, I think we should also raise errors in after(:context) hooks, right?

Maybe we can make a change to rspec-core so this can be:

if RSpec::Core::Hooks::ContextHook === self
  # ...
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if we're going to switch on type like that...could we just include a module with an appropriate method definition in a class like RSpec::Core::Hooks::ContextHook? Seems much more straightforward.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. It seems like the resolution here is to patch something into RSpec core. I'll open an issue over there.

@JonRowe
Copy link
Member

JonRowe commented Dec 9, 2015

Overall this LGTM (I'd rather we had a better way of knowing we were in a hook but if thats the only way then c'est la vie) but the rubocop has a few words to say :)

@fables-tales
Copy link
Member Author

blocked on rspec/rspec-core#2130

fables-tales pushed a commit to rspec/rspec-core that referenced this pull request Dec 10, 2015
This is useful because at the moment the only way to determine if an
example is currently executing a context hook is to look at it's inspect
string. Here, we add a simple boolean flag which is triggered in before
and after context hook execution.

This is needed by rspec/rspec-rails#1501.
fables-tales pushed a commit to rspec/rspec-core that referenced this pull request Dec 10, 2015
This is useful because at the moment the only way to determine if an
example is currently executing a context hook is to look at it's inspect
string. Here, we add a simple boolean flag which is triggered in before
and after context hook execution.

This is needed by rspec/rspec-rails#1501.
new_methods.each do |method_name|
proxy_method_warning_if_called_in_before_context_scope(method_name)
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make this a name module (I'm ok with dynamically creating it) so that it's clear from the ancestor chain we've inserted something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@cupakromer
Copy link
Member

We need to take into account possible global_fixtures. I think this doesn't cover that case. Also note that :all can be provided as an option to allow everything.

@fables-tales
Copy link
Member Author

Can you push a failing test that demonstrates that ?

Sent from my phone please excuse my brevity.

On 10 Dec 2015, at 17:03, Aaron Kromer notifications@github.com wrote:

We need to take into account possible global_fixtures. I think this doesn't cover that case.


Reply to this email directly or view it on GitHub.

@fables-tales
Copy link
Member Author

Also note that :all can be provided as an option to allow everything.

This definitely works for the :all case... we're just capturing all the added methods

myrridin pushed a commit to myrridin/rspec-core that referenced this pull request Dec 11, 2015
This is useful because at the moment the only way to determine if an
example is currently executing a context hook is to look at it's inspect
string. Here, we add a simple boolean flag which is triggered in before
and after context hook execution.

This is needed by rspec/rspec-rails#1501.
@JonRowe
Copy link
Member

JonRowe commented Dec 11, 2015

This just needs @cupakromer's final change made right?

@fables-tales
Copy link
Member Author

@JonRowe I think I understand enough to deal with this myself... I'll get to it a little later today if @cupakromer can't. He's a busy dude and so I'll try to not create any more work for him if I don't need to ^_^

@JonRowe
Copy link
Member

JonRowe commented Dec 11, 2015

Nah I mean his final suggested change ;)

@fables-tales
Copy link
Member Author

@JonRowe totally. I'm planning on getting to that sometime today.

@JonRowe
Copy link
Member

JonRowe commented Dec 11, 2015

👍 :)

@fables-tales
Copy link
Member Author

@cupakromer @JonRowe done the module and the global_fixtures. Can I get a review one more time :) ?

@fables-tales
Copy link
Member Author

@JonRowe @cupakromer I need an opinion here:

Using the module has broken on rails 3.0.20 only because it doesn't use a module, but instead redefines methods on the object proper. We could:

  1. go back to the proxying approach
  2. add conditional logic to use a module on rails versions > 3.0, and proxy only on 3.0

I personally prefer 1 because it will be less code, but makes it slightly harder to debug.

Thoughts please.

Fixes #1442.

The basic approach here is to capture the addition of the fixture
methods to the example group instance and then monkeypatch them. The
monkeypatch checks to see if we're currently in a before(:context) hook
and if we are then it prints a warning and doesn't invoke the method.

The warning here is a little sparse at the moment, and I'd like to make
it more clear. One thing that's a little gross about this implementation
is that it uses the inspect string of the example group to determine if
we're in a before(:context) hook. As far as I can tell there isn't a
better way to make that determination, but maybe someone's got a clever
trick.
@fables-tales
Copy link
Member Author

@JonRowe @cupakromer this is finished. Can one of you give it one last once over.

@JonRowe
Copy link
Member

JonRowe commented Dec 15, 2015

I'm happy with this given the reasoning above.

JonRowe added a commit that referenced this pull request Dec 15, 2015
Warn if a fixture method is called from a `before(:context)` block.
@JonRowe JonRowe merged commit a6bdb46 into master Dec 15, 2015
@JonRowe JonRowe deleted the samphippen/bugfix/1442 branch December 15, 2015 21:10
sebjacobs pushed a commit to futurelearn/rspec-rails that referenced this pull request Mar 15, 2019
MatheusRich pushed a commit to MatheusRich/rspec-core that referenced this pull request Oct 30, 2020
This is useful because at the moment the only way to determine if an
example is currently executing a context hook is to look at it's inspect
string. Here, we add a simple boolean flag which is triggered in before
and after context hook execution.

This is needed by rspec/rspec-rails#1501.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Warn on context fixture helper
4 participants