Skip to content

Commit 096bedf

Browse files
committed
Mark RSpec/IncludeExamples as SafeAutoCorrect: false
1 parent b0fda47 commit 096bedf

File tree

4 files changed

+112
-2
lines changed

4 files changed

+112
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Master (Unreleased)
44

5+
- Mark `RSpec/IncludeExamples` as `SafeAutoCorrect: false`. ([@yujideveloper])
6+
57
## 3.6.0 (2025-04-18)
68

79
- Fix false positive in `RSpec/Pending`, where it would mark the default block `it` as an offense. ([@bquorning])
@@ -1073,5 +1075,6 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
10731075
[@ydah]: https://github.com/ydah
10741076
[@yevhene]: https://github.com/yevhene
10751077
[@ypresto]: https://github.com/ypresto
1078+
[@yujideveloper]: https://github.com/yujideveloper
10761079
[@zdennis]: https://github.com/zdennis
10771080
[@zverok]: https://github.com/zverok

config/default.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,9 @@ RSpec/ImplicitSubject:
535535
RSpec/IncludeExamples:
536536
Description: Checks for usage of `include_examples`.
537537
Enabled: pending
538+
SafeAutoCorrect: false
538539
VersionAdded: '3.6'
540+
VersionChanged: "<<next>>"
539541
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IncludeExamples
540542

541543
RSpec/IndexedLet:

docs/modules/ROOT/pages/cops_rspec.adoc

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,9 +2772,9 @@ it { expect(named_subject).to be_truthy }
27722772
27732773
| Pending
27742774
| Yes
2775-
| Always
2775+
| Always (Unsafe)
27762776
| 3.6
2777-
| -
2777+
| <<next>>
27782778
|===
27792779
27802780
Checks for usage of `include_examples`.
@@ -2786,6 +2786,60 @@ unexpected behavior and side effects.
27862786
27872787
Prefer using `it_behaves_like` instead.
27882788
2789+
----
2790+
2791+
[#safety-rspecincludeexamples]
2792+
=== Safety
2793+
2794+
`include_examples` and `it_behaves_like` have different scoping
2795+
behaviors.
2796+
Changing `include_examples` to `it_behaves_like` creates a new
2797+
context, altering setup dependencies, which can lead to unexpected
2798+
test failures.
2799+
Specifically, the scope of hooks (`before`, `after`, `around`)
2800+
changes, which may prevent expected setup from being inherited
2801+
correctly.
2802+
2803+
Additionally, `let` and `subject` are affected by scoping rules.
2804+
When `include_examples` is used, `let` and `subject` defined within
2805+
`shared_examples` are evaluated in the caller's context, allowing
2806+
access to their values.
2807+
In contrast, `it_behaves_like` creates a new context, preventing
2808+
access to `let` or `subject` values from the caller's context.
2809+
2810+
[source,ruby]
2811+
----
2812+
shared_examples "mock behavior" do
2813+
before do
2814+
allow(service).to receive(:call).and_return("mocked response")
2815+
end
2816+
2817+
it "returns mocked response" do
2818+
expect(service.call).to eq "mocked response"
2819+
end
2820+
end
2821+
2822+
context "working example with include_examples" do
2823+
let(:service) { double(:service) }
2824+
2825+
include_examples "mock behavior"
2826+
2827+
it "uses the mocked service" do
2828+
expect(service.call).to eq "mocked response" # Passes
2829+
end
2830+
end
2831+
2832+
context "broken example with it_behaves_like" do
2833+
let(:service) { double(:service) }
2834+
2835+
it_behaves_like "mock behavior"
2836+
2837+
it "unexpectedly does not use the mocked service" do
2838+
# Fails because `it_behaves_like` does not apply the mock setup
2839+
expect(service.call).to eq "mocked response"
2840+
end
2841+
end
2842+
27892843
[#examples-rspecincludeexamples]
27902844
=== Examples
27912845

lib/rubocop/cop/rspec/include_examples.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,57 @@ module RSpec
1212
#
1313
# Prefer using `it_behaves_like` instead.
1414
#
15+
# @safety
16+
# `include_examples` and `it_behaves_like` have different scoping
17+
# behaviors.
18+
# Changing `include_examples` to `it_behaves_like` creates a new
19+
# context, altering setup dependencies, which can lead to unexpected
20+
# test failures.
21+
# Specifically, the scope of hooks (`before`, `after`, `around`)
22+
# changes, which may prevent expected setup from being inherited
23+
# correctly.
24+
#
25+
# Additionally, `let` and `subject` are affected by scoping rules.
26+
# When `include_examples` is used, `let` and `subject` defined within
27+
# `shared_examples` are evaluated in the caller's context, allowing
28+
# access to their values.
29+
# In contrast, `it_behaves_like` creates a new context, preventing
30+
# access to `let` or `subject` values from the caller's context.
31+
#
32+
# [source,ruby]
33+
# ----
34+
# shared_examples "mock behavior" do
35+
# before do
36+
# allow(service).to receive(:call).and_return("mocked response")
37+
# end
38+
#
39+
# it "returns mocked response" do
40+
# expect(service.call).to eq "mocked response"
41+
# end
42+
# end
43+
#
44+
# context "working example with include_examples" do
45+
# let(:service) { double(:service) }
46+
#
47+
# include_examples "mock behavior"
48+
#
49+
# it "uses the mocked service" do
50+
# expect(service.call).to eq "mocked response" # Passes
51+
# end
52+
# end
53+
#
54+
# context "broken example with it_behaves_like" do
55+
# let(:service) { double(:service) }
56+
#
57+
# it_behaves_like "mock behavior"
58+
#
59+
# it "unexpectedly does not use the mocked service" do
60+
# # Fails because `it_behaves_like` does not apply the mock setup
61+
# expect(service.call).to eq "mocked response"
62+
# end
63+
# end
64+
# ----
65+
#
1566
# @example
1667
# # bad
1768
# include_examples 'examples'

0 commit comments

Comments
 (0)