🆕 RuboCop rule: Prevent hook/let definitions within `each` in RSpec
Problem
In RSpec you can write code like this:
# Bad
RSpec.describe 'Foo' do
[true, false].each do |value|
before do
@value = value
end
it 'works' do
expect(@value).to eq(value)
end
end
Failure
Foo
# order random
works (FAILED - 1)
works
Failures:
1) Foo works
Failure/Error: expect(@value).to eq(value)
expected: true
got: false
(compared using ==)
Diff:
@@ -1 +1 @@
-true
+false
# ./spec/models/foo_spec.rb:12:in `block (3 levels) in <top (required)>'
# ./spec/support/system_exit_detected.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.08224 seconds (files took 3.22 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/models/foo_spec.rb[1:1] # Foo works
Randomized with seed 41211
This code sample above will fail but it's might not always be the case. See the #previous-discussion below.
There are several ways to fix this issue above.
Use context
# Good
RSpec.describe 'Foo' do
[true, false].each do |value|
context "with #{value}" do
before do
@value = value
end
it 'works' do
expect(@value).to eq(value)
end
end
end
end
Use shared_examples
RSpec.describe 'Foo' do
shared_examples 'shared' do |value|
context "with #{value}" do
before do
@value = value
end
it 'works' do
expect(@value).to eq(value)
end
end
end
it_behaves_like 'shared', true
it_behaves_like 'shared', false
end
Use RSpec::Parameterized
# Good
RSpec.describe 'Foo' do
before do
@value = value
end
where(:value) { [true, false] }
with_them do
it 'works' do
expect(@value).to eq(value)
end
end
end
Proposed solution
Create a .each which directly (without extra context/describe) defines hooks like before/after/around.
Link to yet to be created development guidelines in GitLab.org / GitLab in the offense message.
Previous discussion
The following discussion from gitlab-org/gitlab!99026 (closed) should be addressed:
-
@splattael started a discussion: 👋 from https://www.youtube.com/watch?v=CF9Xv1sXQaM🤓 This is a great catch @pslaughter
✨ We might be able to catch those cases via static code analysis in GitLab.org / GitLab by RuboCop to prevent future issues
🤞
Edited by Peter Leitzen