rubocop-rspec 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +23 -0
  4. data/Rakefile +19 -1
  5. data/config/default.yml +78 -15
  6. data/lib/rubocop-rspec.rb +19 -1
  7. data/lib/rubocop/cop/rspec/any_instance.rb +5 -1
  8. data/lib/rubocop/cop/rspec/be_eql.rb +58 -0
  9. data/lib/rubocop/cop/rspec/describe_class.rb +2 -3
  10. data/lib/rubocop/cop/rspec/describe_method.rb +4 -3
  11. data/lib/rubocop/cop/rspec/described_class.rb +4 -35
  12. data/lib/rubocop/cop/rspec/empty_example_group.rb +100 -0
  13. data/lib/rubocop/cop/rspec/example_length.rb +5 -2
  14. data/lib/rubocop/cop/rspec/example_wording.rb +5 -2
  15. data/lib/rubocop/cop/rspec/expect_actual.rb +79 -0
  16. data/lib/rubocop/cop/rspec/file_path.rb +3 -1
  17. data/lib/rubocop/cop/rspec/focus.rb +12 -28
  18. data/lib/rubocop/cop/rspec/hook_argument.rb +122 -0
  19. data/lib/rubocop/cop/rspec/instance_variable.rb +53 -12
  20. data/lib/rubocop/cop/rspec/leading_subject.rb +58 -0
  21. data/lib/rubocop/cop/rspec/let_setup.rb +58 -0
  22. data/lib/rubocop/cop/rspec/message_chain.rb +33 -0
  23. data/lib/rubocop/cop/rspec/message_expectation.rb +58 -0
  24. data/lib/rubocop/cop/rspec/multiple_describes.rb +10 -7
  25. data/lib/rubocop/cop/rspec/multiple_expectations.rb +89 -0
  26. data/lib/rubocop/cop/rspec/named_subject.rb +10 -1
  27. data/lib/rubocop/cop/rspec/nested_groups.rb +125 -0
  28. data/lib/rubocop/cop/rspec/not_to_not.rb +3 -3
  29. data/lib/rubocop/cop/rspec/subject_stub.rb +136 -0
  30. data/lib/rubocop/cop/rspec/verified_doubles.rb +4 -1
  31. data/lib/rubocop/rspec.rb +10 -0
  32. data/lib/rubocop/rspec/config_formatter.rb +33 -0
  33. data/lib/rubocop/rspec/description_extractor.rb +35 -0
  34. data/lib/rubocop/rspec/inject.rb +2 -6
  35. data/lib/rubocop/rspec/language.rb +73 -0
  36. data/lib/rubocop/rspec/language/node_pattern.rb +16 -0
  37. data/lib/rubocop/rspec/spec_only.rb +61 -0
  38. data/lib/rubocop/rspec/top_level_describe.rb +6 -0
  39. data/lib/rubocop/rspec/version.rb +1 -1
  40. data/rubocop-rspec.gemspec +1 -0
  41. data/spec/project/changelog_spec.rb +81 -0
  42. data/spec/project/default_config_spec.rb +52 -0
  43. data/spec/project/project_requires_spec.rb +8 -0
  44. data/spec/rubocop/cop/rspec/be_eql_spec.rb +59 -0
  45. data/spec/rubocop/cop/rspec/described_class_spec.rb +2 -2
  46. data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +79 -0
  47. data/spec/rubocop/cop/rspec/example_length_spec.rb +50 -30
  48. data/spec/rubocop/cop/rspec/example_wording_spec.rb +21 -3
  49. data/spec/rubocop/cop/rspec/expect_actual_spec.rb +136 -0
  50. data/spec/rubocop/cop/rspec/file_path_spec.rb +48 -71
  51. data/spec/rubocop/cop/rspec/focus_spec.rb +1 -1
  52. data/spec/rubocop/cop/rspec/hook_argument_spec.rb +189 -0
  53. data/spec/rubocop/cop/rspec/instance_variable_spec.rb +37 -0
  54. data/spec/rubocop/cop/rspec/leading_subject_spec.rb +54 -0
  55. data/spec/rubocop/cop/rspec/let_setup_spec.rb +66 -0
  56. data/spec/rubocop/cop/rspec/message_chain_spec.rb +21 -0
  57. data/spec/rubocop/cop/rspec/message_expectation_spec.rb +63 -0
  58. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +84 -0
  59. data/spec/rubocop/cop/rspec/nested_groups_spec.rb +55 -0
  60. data/spec/rubocop/cop/rspec/not_to_not_spec.rb +12 -2
  61. data/spec/rubocop/cop/rspec/subject_stub_spec.rb +183 -0
  62. data/spec/rubocop/rspec/config_formatter_spec.rb +48 -0
  63. data/spec/rubocop/rspec/description_extractor_spec.rb +35 -0
  64. data/spec/rubocop/rspec/language/selector_set_spec.rb +29 -0
  65. data/spec/rubocop/rspec/spec_only_spec.rb +97 -0
  66. data/spec/shared/rspec_only_cop_behavior.rb +68 -0
  67. data/spec/spec_helper.rb +13 -1
  68. metadata +72 -5
  69. data/spec/project_spec.rb +0 -115
@@ -35,4 +35,41 @@ describe RuboCop::Cop::RSpec::InstanceVariable do
35
35
  @foo.empty?
36
36
  RUBY
37
37
  end
38
+
39
+ # Regression test for nevir/rubocop-rspec#115
40
+ it 'ignores instance variables outside of specs' do
41
+ expect_no_violations(<<-RUBY, filename: 'lib/source_code.rb')
42
+ feature do
43
+ @foo = bar
44
+
45
+ @foo
46
+ end
47
+ RUBY
48
+ end
49
+
50
+ context 'when configured with AssignmentOnly', :config do
51
+ subject(:cop) { described_class.new(config) }
52
+
53
+ let(:cop_config) do
54
+ { 'AssignmentOnly' => true }
55
+ end
56
+
57
+ it 'flags an instance variable when it is also assigned' do
58
+ expect_violation(<<-RUBY)
59
+ describe MyClass do
60
+ before { @foo = [] }
61
+ it { expect(@foo).to be_empty }
62
+ ^^^^ Use `let` instead of an instance variable
63
+ end
64
+ RUBY
65
+ end
66
+
67
+ it 'ignores an instance variable when it is not assigned' do
68
+ expect_no_violations(<<-RUBY)
69
+ describe MyClass do
70
+ it { expect(@foo).to be_empty }
71
+ end
72
+ RUBY
73
+ end
74
+ end
38
75
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RuboCop::Cop::RSpec::LeadingSubject do
4
+ subject(:cop) { described_class.new }
5
+
6
+ it 'checks subject below let' do
7
+ expect_violation(<<-RUBY)
8
+ RSpec.describe User do
9
+ let(:params) { foo }
10
+
11
+ subject { described_class.new }
12
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `let` declarations
13
+ end
14
+ RUBY
15
+ end
16
+
17
+ it 'approves of subject above let' do
18
+ expect_no_violations(<<-RUBY)
19
+ RSpec.describe User do
20
+ context 'blah' do
21
+ end
22
+
23
+ subject { described_class.new }
24
+
25
+ let(:params) { foo }
26
+ end
27
+ RUBY
28
+ end
29
+
30
+ it 'handles subjects in contexts' do
31
+ expect_no_violations(<<-RUBY)
32
+ RSpec.describe User do
33
+ let(:params) { foo }
34
+
35
+ context "when something happens" do
36
+ subject { described_class.new }
37
+ end
38
+ end
39
+ RUBY
40
+ end
41
+
42
+ it 'handles subjects in tests' do
43
+ expect_no_violations(<<-RUBY)
44
+ RSpec.describe User do
45
+ # This shouldn't really ever happen in a sane codebase but I still
46
+ # want to avoid false positives
47
+ it "doesn't mind me calling a method called subject in the test" do
48
+ let(foo)
49
+ subject { bar }
50
+ end
51
+ end
52
+ RUBY
53
+ end
54
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RuboCop::Cop::RSpec::LetSetup do
4
+ subject(:cop) { described_class.new }
5
+
6
+ it 'complains when let! is used and not referenced' do
7
+ expect_violation(<<-RUBY)
8
+ describe Foo do
9
+ let!(:foo) { bar }
10
+ ^^^^^^^^^^ Do not use `let!` for test setup.
11
+
12
+ it 'does not use foo' do
13
+ expect(baz).to eq(qux)
14
+ end
15
+ end
16
+ RUBY
17
+ end
18
+
19
+ it 'ignores let! when used in `before`' do
20
+ expect_no_violations(<<-RUBY)
21
+ describe Foo do
22
+ let!(:foo) { bar }
23
+
24
+ before do
25
+ foo
26
+ end
27
+
28
+ it 'does not use foo' do
29
+ expect(baz).to eq(qux)
30
+ end
31
+ end
32
+ RUBY
33
+ end
34
+
35
+ it 'ignores let! when used in example' do
36
+ expect_no_violations(<<-RUBY)
37
+ describe Foo do
38
+ let!(:foo) { bar }
39
+
40
+ it 'uses foo' do
41
+ foo
42
+ expect(baz).to eq(qux)
43
+ end
44
+ end
45
+ RUBY
46
+ end
47
+
48
+ it 'complains when let! is used and not referenced within nested group' do
49
+ expect_violation(<<-RUBY)
50
+ describe Foo do
51
+ context 'when something special happens' do
52
+ let!(:foo) { bar }
53
+ ^^^^^^^^^^ Do not use `let!` for test setup.
54
+
55
+ it 'does not use foo' do
56
+ expect(baz).to eq(qux)
57
+ end
58
+ end
59
+
60
+ it 'references some other foo' do
61
+ foo
62
+ end
63
+ end
64
+ RUBY
65
+ end
66
+ end
@@ -0,0 +1,21 @@
1
+ describe RuboCop::Cop::RSpec::MessageChain do
2
+ subject(:cop) { described_class.new }
3
+
4
+ it 'finds `receive_message_chain`' do
5
+ expect_violation(<<-RUBY)
6
+ before do
7
+ allow(foo).to receive_message_chain(:one, :two) { :three }
8
+ ^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `receive_message_chain`
9
+ end
10
+ RUBY
11
+ end
12
+
13
+ it 'finds old `stub_chain` syntax' do
14
+ expect_violation(<<-RUBY)
15
+ before do
16
+ foo.stub_chain(:one, :two).and_return(:three)
17
+ ^^^^^^^^^^ Avoid stubbing using `stub_chain`
18
+ end
19
+ RUBY
20
+ end
21
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RuboCop::Cop::RSpec::MessageExpectation, :config do
4
+ subject(:cop) { described_class.new(config) }
5
+
6
+ context 'when EnforcedStyle is allow' do
7
+ let(:cop_config) do
8
+ { 'EnforcedStyle' => 'allow' }
9
+ end
10
+
11
+ it 'flags expect(...).to receive' do
12
+ expect_violation(<<-RUBY)
13
+ expect(foo).to receive(:bar)
14
+ ^^^^^^ Prefer `allow` for setting message expectations.
15
+ RUBY
16
+ end
17
+
18
+ it 'approves of allow(...).to receive' do
19
+ expect_no_violations('allow(foo).to receive(:bar)')
20
+ end
21
+
22
+ it 'generates a todo based on the usage of the correct style' do
23
+ inspect_source(cop, 'allow(foo).to receive(:bar)', 'foo_spec.rb')
24
+
25
+ expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'allow')
26
+ end
27
+
28
+ it 'generates a todo based on the usage of the alternate style' do
29
+ inspect_source(cop, 'expect(foo).to receive(:bar)', 'foo_spec.rb')
30
+
31
+ expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'expect')
32
+ end
33
+ end
34
+
35
+ context 'when EnforcedStyle is expect' do
36
+ let(:cop_config) do
37
+ { 'EnforcedStyle' => 'expect' }
38
+ end
39
+
40
+ it 'flags allow(...).to receive' do
41
+ expect_violation(<<-RUBY)
42
+ allow(foo).to receive(:bar)
43
+ ^^^^^ Prefer `expect` for setting message expectations.
44
+ RUBY
45
+ end
46
+
47
+ it 'approves of expect(...).to receive' do
48
+ expect_no_violations('expect(foo).to receive(:bar)')
49
+ end
50
+
51
+ it 'generates a todo based on the usage of the correct style' do
52
+ inspect_source(cop, 'expect(foo).to receive(:bar)', 'foo_spec.rb')
53
+
54
+ expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'expect')
55
+ end
56
+
57
+ it 'generates a todo based on the usage of the alternate style' do
58
+ inspect_source(cop, 'allow(foo).to receive(:bar)', 'foo_spec.rb')
59
+
60
+ expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'allow')
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
4
+ subject(:cop) { described_class.new(config) }
5
+
6
+ context 'without configuration' do
7
+ let(:cop_config) { Hash.new }
8
+
9
+ it 'flags multiple expectations' do
10
+ expect_violation(<<-RUBY)
11
+ describe Foo do
12
+ it 'uses expect twice' do
13
+ ^^^^^^^^^^^^^^^^^^^^^^ Too many expectations.
14
+ expect(foo).to eq(bar)
15
+ expect(baz).to eq(bar)
16
+ end
17
+ end
18
+ RUBY
19
+ end
20
+
21
+ it 'approves of one expectation per example' do
22
+ expect_no_violations(<<-RUBY)
23
+ describe Foo do
24
+ it 'does something neat' do
25
+ expect(neat).to be(true)
26
+ end
27
+
28
+ it 'does something cool' do
29
+ expect(cool).to be(true)
30
+ end
31
+ end
32
+ RUBY
33
+ end
34
+ end
35
+
36
+ context 'with configuration' do
37
+ let(:cop_config) do
38
+ { 'Max' => '2' }
39
+ end
40
+
41
+ it 'permits two expectations' do
42
+ expect_no_violations(<<-RUBY)
43
+ describe Foo do
44
+ it 'uses expect twice' do
45
+ expect(foo).to eq(bar)
46
+ expect(baz).to eq(bar)
47
+ end
48
+ end
49
+ RUBY
50
+ end
51
+
52
+ it 'flags three expectations' do
53
+ expect_violation(<<-RUBY)
54
+ describe Foo do
55
+ it 'uses expect three times' do
56
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Too many expectations.
57
+ expect(foo).to eq(bar)
58
+ expect(baz).to eq(bar)
59
+ expect(qux).to eq(bar)
60
+ end
61
+ end
62
+ RUBY
63
+ end
64
+ end
65
+
66
+ it 'generates a todo based on the worst violation' do
67
+ inspect_source(cop, <<-RUBY, 'spec/foo_spec.rb')
68
+ describe Foo do
69
+ it 'uses expect twice' do
70
+ expect(foo).to eq(bar)
71
+ expect(baz).to eq(bar)
72
+ end
73
+
74
+ it 'uses expect three times' do
75
+ expect(foo).to eq(bar)
76
+ expect(baz).to eq(bar)
77
+ expect(qux).to eq(bar)
78
+ end
79
+ end
80
+ RUBY
81
+
82
+ expect(cop.config_to_allow_offenses).to eq('Max' => 3)
83
+ end
84
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RuboCop::Cop::RSpec::NestedGroups, :config do
4
+ subject(:cop) { described_class.new(config) }
5
+
6
+ it 'flags nested contexts' do
7
+ expect_violation(<<-RUBY)
8
+ describe MyClass do
9
+ context 'when foo' do
10
+ context 'when bar' do
11
+ ^^^^^^^^^^^^^^^^^^ Maximum example group nesting exceeded
12
+ context 'when baz' do
13
+ ^^^^^^^^^^^^^^^^^^ Maximum example group nesting exceeded
14
+ end
15
+ end
16
+ end
17
+
18
+ context 'when qux' do
19
+ context 'when norf' do
20
+ ^^^^^^^^^^^^^^^^^^^ Maximum example group nesting exceeded
21
+ end
22
+ end
23
+ end
24
+ RUBY
25
+ end
26
+
27
+ it 'ignores non-spec context methods' do
28
+ expect_no_violations(<<-RUBY)
29
+ class MyThingy
30
+ context 'this is not rspec' do
31
+ context 'but it uses contexts' do
32
+ end
33
+ end
34
+ end
35
+ RUBY
36
+ end
37
+
38
+ context 'when MaxNesting is configured as 2' do
39
+ let(:cop_config) { { 'MaxNesting' => '3' } }
40
+
41
+ it 'only flags third level of nesting' do
42
+ expect_violation(<<-RUBY)
43
+ describe MyClass do
44
+ context 'when foo' do
45
+ context 'when bar' do
46
+ context 'when baz' do
47
+ ^^^^^^^^^^^^^^^^^^ Maximum example group nesting exceeded
48
+ end
49
+ end
50
+ end
51
+ end
52
+ RUBY
53
+ end
54
+ end
55
+ end
@@ -18,7 +18,12 @@ describe RuboCop::Cop::RSpec::NotToNot, :config do
18
18
  end
19
19
 
20
20
  it 'auto-corrects `to_not` to `not_to`' do
21
- corrected = autocorrect_source(cop, ['it { expect(0).to_not equal 1 }'])
21
+ corrected =
22
+ autocorrect_source(
23
+ cop,
24
+ ['it { expect(0).to_not equal 1 }'],
25
+ 'spec/foo_spec.rb'
26
+ )
22
27
  expect(corrected).to eq 'it { expect(0).not_to equal 1 }'
23
28
  end
24
29
  end
@@ -40,7 +45,12 @@ describe RuboCop::Cop::RSpec::NotToNot, :config do
40
45
  end
41
46
 
42
47
  it 'auto-corrects `not_to` to `to_not`' do
43
- corrected = autocorrect_source(cop, ['it { expect(0).not_to equal 1 }'])
48
+ corrected =
49
+ autocorrect_source(
50
+ cop,
51
+ ['it { expect(0).not_to equal 1 }'],
52
+ 'spec/foo_spec.rb'
53
+ )
44
54
  expect(corrected).to eq 'it { expect(0).to_not equal 1 }'
45
55
  end
46
56
  end
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RuboCop::Cop::RSpec::SubjectStub do
4
+ subject(:cop) { described_class.new }
5
+
6
+ it 'complains when subject is stubbed' do
7
+ expect_violation(<<-RUBY)
8
+ describe Foo do
9
+ subject(:foo) { described_class.new }
10
+
11
+ before do
12
+ allow(foo).to receive(:bar).and_return(baz)
13
+ ^^^^^^^^^^ Do not stub your test subject.
14
+ end
15
+
16
+ it 'uses expect twice' do
17
+ expect(foo.bar).to eq(baz)
18
+ end
19
+ end
20
+ RUBY
21
+ end
22
+
23
+ it 'complains when subject is mocked' do
24
+ expect_violation(<<-RUBY)
25
+ describe Foo do
26
+ subject(:foo) { described_class.new }
27
+
28
+ before do
29
+ expect(foo).to receive(:bar).and_return(baz)
30
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
31
+ expect(foo).to receive(:bar)
32
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
33
+ expect(foo).to receive(:bar).with(1)
34
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
35
+ expect(foo).to receive(:bar).with(1).and_return(2)
36
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
37
+ end
38
+
39
+ it 'uses expect twice' do
40
+ expect(foo.bar).to eq(baz)
41
+ end
42
+ end
43
+ RUBY
44
+ end
45
+
46
+ it 'ignores stub within context where subject name changed' do
47
+ expect_no_violations(<<-RUBY)
48
+ describe Foo do
49
+ subject(:foo) { described_class.new }
50
+
51
+ context 'when I shake things up' do
52
+ subject(:bar) { described_class.new }
53
+
54
+ it 'tries to trick rubocop-rspec' do
55
+ allow(foo).to receive(:baz)
56
+ end
57
+ end
58
+ end
59
+ RUBY
60
+ end
61
+
62
+ it 'flags nested subject stubs when nested subject uses same name' do
63
+ expect_violation(<<-RUBY)
64
+ describe Foo do
65
+ subject(:foo) { described_class.new }
66
+
67
+ context 'when I shake things up' do
68
+ subject(:foo) { described_class.new }
69
+
70
+ before do
71
+ allow(foo).to receive(:wow)
72
+ ^^^^^^^^^^ Do not stub your test subject.
73
+ end
74
+
75
+ it 'tries to trick rubocop-rspec' do
76
+ expect(foo).to eql(:neat)
77
+ end
78
+ end
79
+ end
80
+ RUBY
81
+ end
82
+
83
+ it 'ignores nested stubs when nested subject is anonymous' do
84
+ expect_no_violations(<<-RUBY)
85
+ describe Foo do
86
+ subject(:foo) { described_class.new }
87
+
88
+ context 'when I shake things up' do
89
+ subject { described_class.new }
90
+
91
+ before do
92
+ allow(foo).to receive(:wow)
93
+ end
94
+
95
+ it 'tries to trick rubocop-rspec' do
96
+ expect(foo).to eql(:neat)
97
+ end
98
+ end
99
+ end
100
+ RUBY
101
+ end
102
+
103
+ it 'flags nested subject stubs when example group does not define subject' do
104
+ expect_violation(<<-RUBY)
105
+ describe Foo do
106
+ subject(:foo) { described_class.new }
107
+
108
+ context 'when I shake things up' do
109
+ before do
110
+ allow(foo).to receive(:wow)
111
+ ^^^^^^^^^^ Do not stub your test subject.
112
+ end
113
+
114
+ it 'tries to trick rubocop-rspec' do
115
+ expect(foo).to eql(:neat)
116
+ end
117
+ end
118
+ end
119
+ RUBY
120
+ end
121
+
122
+ it 'flags nested subject stubs' do
123
+ expect_violation(<<-RUBY)
124
+ describe Foo do
125
+ subject(:foo) { described_class.new }
126
+
127
+ context 'when I shake things up' do
128
+ subject(:bar) { described_class.new }
129
+
130
+ before do
131
+ allow(foo).to receive(:wow)
132
+ allow(bar).to receive(:wow)
133
+ ^^^^^^^^^^ Do not stub your test subject.
134
+ end
135
+
136
+ it 'tries to trick rubocop-rspec' do
137
+ expect(bar).to eql(foo)
138
+ end
139
+ end
140
+ end
141
+ RUBY
142
+ end
143
+
144
+ it 'flags nested subject stubs when adjacent context redefines' do
145
+ expect_violation(<<-RUBY)
146
+ describe Foo do
147
+ subject(:foo) { described_class.new }
148
+
149
+ context 'when I do something in a context' do
150
+ subject { blah }
151
+ end
152
+
153
+ it 'still flags this test' do
154
+ allow(foo).to receive(:blah)
155
+ ^^^^^^^^^^ Do not stub your test subject.
156
+ end
157
+ end
158
+ RUBY
159
+ end
160
+
161
+ it 'flags deeply nested subject stubs' do
162
+ expect_violation(<<-RUBY)
163
+ describe Foo do
164
+ subject(:foo) { described_class.new }
165
+
166
+ context 'level 1' do
167
+ subject(:bar) { described_class.new }
168
+
169
+ context 'level 2' do
170
+ subject(:baz) { described_class.new }
171
+
172
+ before do
173
+ allow(foo).to receive(:wow)
174
+ allow(bar).to receive(:wow)
175
+ allow(baz).to receive(:wow)
176
+ ^^^^^^^^^^ Do not stub your test subject.
177
+ end
178
+ end
179
+ end
180
+ end
181
+ RUBY
182
+ end
183
+ end