-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Warn on context fixture helper #1208
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
module RSpec | ||
module Rails | ||
# @private | ||
module FixtureContextHelpers | ||
# @private | ||
module TrackableFixtures | ||
def known_fixtures | ||
@_known_fixtures ||= [] | ||
end | ||
|
||
def to_s | ||
"#{super}(#{known_fixtures.sort.join(', ')})" | ||
end | ||
alias_method :inspect, :to_s | ||
end | ||
|
||
private | ||
|
||
def convert_to_accessors(names) | ||
names.map { |n| n.to_s.tr('/', '_').to_sym } | ||
end | ||
|
||
def ensure_prevent_fixture_helpers | ||
if const_defined?(:PreventFixtures, false) | ||
const_get(:PreventFixtures, false) | ||
else | ||
set_prevent_fixture_helpers | ||
end | ||
end | ||
|
||
def prevent_fixture_helpers | ||
const_get(:PreventFixtures) if const_defined?(:PreventFixtures) | ||
end | ||
|
||
def prevent_fixtures_in_context(accessor_names) | ||
return if accessor_names.empty? | ||
ensure_prevent_fixture_helpers.module_exec do | ||
(accessor_names - known_fixtures).each do |accessor_name| | ||
known_fixtures << accessor_name | ||
define_method(accessor_name) do |*_fixture_names| | ||
raise <<-EOS | ||
Fixture accessor `#{accessor_name}` invoked in a `before` or `after` context hook at: | ||
#{CallerFilter.first_non_rspec_line} | ||
|
||
Calling fixture accessors from a context hook is not supported. | ||
|
||
Active Record fixtures are automatically loaded into the database before each | ||
example. To ensure consistent data, the environment deletes the fixtures before | ||
running the load each time. | ||
|
||
Fixture accessor helpers are not intended to be called in a context hook, as | ||
they exist to load database state that is reset between each example, while | ||
`before(:context)` exists to define state that is shared across examples in an | ||
example group and `after(:context)` exists to cleanup state that is shared | ||
across examples in an example group. | ||
EOS | ||
end | ||
end | ||
end | ||
end | ||
|
||
def set_prevent_fixture_helpers | ||
existing_helpers = prevent_fixture_helpers | ||
mod = Module.new do | ||
extend TrackableFixtures | ||
include existing_helpers if existing_helpers | ||
end | ||
const_set(:PreventFixtures, mod) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
require_relative 'fixture_context_helpers' | ||
module RSpec | ||
module Rails | ||
# @private | ||
|
@@ -26,6 +27,34 @@ module FixtureSupport | |
self.use_instantiated_fixtures = RSpec.configuration.use_instantiated_fixtures | ||
fixtures RSpec.configuration.global_fixtures if RSpec.configuration.global_fixtures | ||
end | ||
|
||
# @private | ||
module ClassMethods | ||
include RSpec::Rails::FixtureContextHelpers | ||
|
||
def run_before_context_hooks(example_group_instance) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As you commented, it would be nice not to hook into a private rspec-core API like this. This may not continue working, for example, with the changes coming in rspec/rspec-core#1749. I was also realizing that this issue bears similarity to the use of Thinking out loud about a possible solution...there's nothing that says the example group instance used for That said...I'm realizing that such a solution probably wouldn't play well with the changes in rspec/rspec-core#1749 since I'm working there on making shared contexts (including Any ideas on what rspec-core could do to facilitate this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, I copied the wording and logic from there.
I believe there likely are. I know rspec-mocks would benefits from some helpful messages in
This would be ideal. That way any gem could hook into this process.
Not at this time. I'll need to review your PR a bit more to understand what is going on there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It sounds like the status of that other PR will affect what we do here...so I'm going to try to wrap up the rspec-core PR in the next day or two. |
||
if (_helpers = prevent_fixture_helpers) | ||
example_group_instance.extend _helpers | ||
end | ||
super | ||
end | ||
private :run_before_context_hooks | ||
|
||
def run_after_context_hooks(example_group_instance) | ||
if (_helpers = prevent_fixture_helpers) | ||
example_group_instance.extend _helpers | ||
end | ||
super | ||
end | ||
private :run_before_context_hooks | ||
|
||
def setup_fixture_accessors(table_names = nil) | ||
fixture_set_names = Array(fixture_set_names || fixture_table_names) | ||
prevent_fixtures_in_context(convert_to_accessors(fixture_set_names)) | ||
super | ||
end | ||
private :setup_fixture_accessors | ||
end | ||
end | ||
end | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
before(:context)
orafter(:context)
is clearer thanbefore
orafter
context.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I'll fix that up