rubocop-rspec 1.11.0 → 1.12.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/config/default.yml +12 -0
- data/lib/rubocop-rspec.rb +2 -0
- data/lib/rubocop/cop/rspec/before_after_all.rb +50 -0
- data/lib/rubocop/cop/rspec/instance_spy.rb +70 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/spec/rubocop/cop/rspec/before_after_all_spec.rb +92 -0
- data/spec/rubocop/cop/rspec/instance_spy_spec.rb +60 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48bfb61579b01b4044eeca76aa125c026ac18630
|
4
|
+
data.tar.gz: 240d2ce3b483174eae7c4049fcc65f8301bf48a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09f351caba55c9c7ad8710e286fec4b9f087028a64a886c4edf25d69b3147ecedebd5e7eeacec52a81285e14c3cd46cf615fbfef3c15a542fe6cd6c6a9d28a0c
|
7
|
+
data.tar.gz: 120152a6271b3eb853a9e8c4b19716667b401f732a712c045ebada5df7371c3a843e49d5a8a83cb5197fd7a9bbf4a12e6ef245fdf9df9cd26155a849cdcdeffc
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
-
## Master (
|
3
|
+
## Master (Unreleased)
|
4
|
+
|
5
|
+
## 1.12.0 (2017-02-21)
|
6
|
+
|
7
|
+
* Add `RSpec/InstanceSpy` cop. ([@Darhazer][])
|
8
|
+
* Add `RSpec/BeforeAfterAll` for avoiding leaky global test setup. ([@cfabianski][])
|
4
9
|
|
5
10
|
## 1.11.0 (2017-02-16)
|
6
11
|
|
@@ -180,3 +185,4 @@
|
|
180
185
|
[@onk]: https://github.com/onk
|
181
186
|
[@Darhazer]: https://github.com/Darhazer
|
182
187
|
[@redross]: https://github.com/redross
|
188
|
+
[@cfabianski]: https://github.com/cfabianski
|
data/config/default.yml
CHANGED
@@ -17,6 +17,14 @@ RSpec/BeEql:
|
|
17
17
|
Description: Check for expectations where `be(...)` can replace `eql(...)`.
|
18
18
|
Enabled: true
|
19
19
|
|
20
|
+
RSpec/BeforeAfterAll:
|
21
|
+
Description: Check that before/after(:all) isn't being used.
|
22
|
+
Enabled: true
|
23
|
+
Exclude:
|
24
|
+
- spec/spec_helper.rb
|
25
|
+
- spec/rails_helper.rb
|
26
|
+
- spec/support/**/*.rb
|
27
|
+
|
20
28
|
RSpec/DescribeClass:
|
21
29
|
Description: Check that the first argument to the top level describe is a constant.
|
22
30
|
Enabled: true
|
@@ -90,6 +98,10 @@ RSpec/ImplicitExpect:
|
|
90
98
|
- is_expected
|
91
99
|
- should
|
92
100
|
|
101
|
+
RSpec/InstanceSpy:
|
102
|
+
Description: Checks for `instance_double` used with `have_received`.
|
103
|
+
Enabled: true
|
104
|
+
|
93
105
|
RSpec/InstanceVariable:
|
94
106
|
Description: Checks for instance variable usage in specs.
|
95
107
|
AssignmentOnly: false
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -23,6 +23,7 @@ RuboCop::RSpec::Inject.defaults!
|
|
23
23
|
require 'rubocop/cop/rspec/any_instance'
|
24
24
|
require 'rubocop/cop/rspec/around_block'
|
25
25
|
require 'rubocop/cop/rspec/be_eql'
|
26
|
+
require 'rubocop/cop/rspec/before_after_all'
|
26
27
|
require 'rubocop/cop/rspec/describe_class'
|
27
28
|
require 'rubocop/cop/rspec/describe_method'
|
28
29
|
require 'rubocop/cop/rspec/described_class'
|
@@ -35,6 +36,7 @@ require 'rubocop/cop/rspec/file_path'
|
|
35
36
|
require 'rubocop/cop/rspec/focus'
|
36
37
|
require 'rubocop/cop/rspec/hook_argument'
|
37
38
|
require 'rubocop/cop/rspec/implicit_expect'
|
39
|
+
require 'rubocop/cop/rspec/instance_spy'
|
38
40
|
require 'rubocop/cop/rspec/instance_variable'
|
39
41
|
require 'rubocop/cop/rspec/leading_subject'
|
40
42
|
require 'rubocop/cop/rspec/let_setup'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Check that before/after(:all) isn't being used.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# #
|
11
|
+
# # Faster but risk of state leaking between examples
|
12
|
+
# #
|
13
|
+
# describe MyClass do
|
14
|
+
# before(:all) { Widget.create }
|
15
|
+
# after(:all) { Widget.delete_all }
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# #
|
20
|
+
# # Slower but examples are properly isolated
|
21
|
+
# #
|
22
|
+
# describe MyClass do
|
23
|
+
# before(:each) { Widget.create }
|
24
|
+
# after(:each) { Widget.delete_all }
|
25
|
+
# end
|
26
|
+
class BeforeAfterAll < Cop
|
27
|
+
MESSAGE = 'Beware of using `before/after(:all)` as it may cause state '\
|
28
|
+
'to leak between tests. If you are using rspec-rails, and '\
|
29
|
+
'`use_transactional_fixtures` is enabled, then records created in '\
|
30
|
+
'`before(:all)` are not rolled back.'.freeze
|
31
|
+
|
32
|
+
BEFORE_AFTER_METHODS = [
|
33
|
+
:before,
|
34
|
+
:after
|
35
|
+
].freeze
|
36
|
+
|
37
|
+
ALL_PAIR = s(:sym, :all)
|
38
|
+
CONTEXT_PAIR = s(:sym, :context)
|
39
|
+
|
40
|
+
def on_send(node)
|
41
|
+
_receiver, method_name, *args = *node
|
42
|
+
return unless BEFORE_AFTER_METHODS.include?(method_name)
|
43
|
+
return unless args.include?(ALL_PAIR) || args.include?(CONTEXT_PAIR)
|
44
|
+
|
45
|
+
add_offense(node, :expression, MESSAGE)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for `instance_double` used with `have_received`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# it do
|
11
|
+
# foo = instance_double(Foo).as_null_object
|
12
|
+
# expect(foo).to have_received(:bar)
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# it do
|
17
|
+
# foo = instance_spy(Foo)
|
18
|
+
# expect(foo).to have_received(:bar)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
class InstanceSpy < Cop
|
22
|
+
MSG = 'Use `instance_spy` when you check your double ' \
|
23
|
+
'with `have_received`'.freeze
|
24
|
+
|
25
|
+
EXAMPLES = Examples::ALL.node_pattern_union.freeze
|
26
|
+
|
27
|
+
def_node_matcher :example?, "(block $(send nil #{EXAMPLES}) ...)"
|
28
|
+
|
29
|
+
def_node_search :null_double, <<-PATTERN
|
30
|
+
(lvasgn $_
|
31
|
+
(send
|
32
|
+
$(send nil :instance_double
|
33
|
+
...) :as_null_object))
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def_node_search :have_received_usage, <<-PATTERN
|
37
|
+
(send
|
38
|
+
(send nil :expect
|
39
|
+
(lvar $_)) :to
|
40
|
+
(send nil :have_received
|
41
|
+
...)
|
42
|
+
...)
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
def on_block(node)
|
46
|
+
return unless example?(node)
|
47
|
+
|
48
|
+
null_double(node) do |var, receiver|
|
49
|
+
have_received_usage(node) do |expected|
|
50
|
+
add_offense(receiver, :expression, MSG) if expected == var
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def autocorrect(node)
|
56
|
+
lambda do |corrector|
|
57
|
+
replacement = 'instance_spy'
|
58
|
+
corrector.replace(node.loc.selector, replacement)
|
59
|
+
|
60
|
+
double_source_map = node.parent.loc
|
61
|
+
as_null_object_range = double_source_map
|
62
|
+
.dot
|
63
|
+
.join(double_source_map.selector)
|
64
|
+
corrector.remove(as_null_object_range)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
describe RuboCop::Cop::RSpec::BeforeAfterAll, :config do
|
2
|
+
subject(:cop) { described_class.new(config) }
|
3
|
+
|
4
|
+
context 'when offenses detected' do
|
5
|
+
let(:code) do
|
6
|
+
[
|
7
|
+
'describe MyClass do',
|
8
|
+
' before(:all) { do_something}',
|
9
|
+
' after(:all) { do_something_else }',
|
10
|
+
'end'
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:expected_error) do
|
15
|
+
'Beware of using `before/after(:all)` as it may cause state to leak '\
|
16
|
+
'between tests. If you are using rspec-rails, and '\
|
17
|
+
'`use_transactional_fixtures` is enabled, then records created in '\
|
18
|
+
'`before(:all)` are not rolled back.'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'reports 2 offenses' do
|
22
|
+
inspect_source(cop, code, 'foo_spec.rb')
|
23
|
+
expect(cop.offenses.size).to eq(2)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'reports the lines for these offenses' do
|
27
|
+
inspect_source(cop, code, 'foo_spec.rb')
|
28
|
+
expect(cop.offenses.map(&:line).sort).to eq([2, 3])
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'describes the offenses' do
|
32
|
+
inspect_source(cop, code, 'foo_spec.rb')
|
33
|
+
expect(cop.messages).to eq([expected_error, expected_error])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'complains for :context' do
|
38
|
+
inspect_source(
|
39
|
+
cop,
|
40
|
+
[
|
41
|
+
'describe MyClass do',
|
42
|
+
' before(:context) { do_something }',
|
43
|
+
' after(:context) { do_something_else }',
|
44
|
+
'end'
|
45
|
+
],
|
46
|
+
'foo_spec.rb'
|
47
|
+
)
|
48
|
+
expect(cop.offenses.size).to eq(2)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'does not complain for before/after :each' do
|
52
|
+
inspect_source(
|
53
|
+
cop,
|
54
|
+
[
|
55
|
+
'describe MyClass do',
|
56
|
+
' before(:each) { do_something }',
|
57
|
+
' after(:each) { do_something_else }',
|
58
|
+
'end'
|
59
|
+
],
|
60
|
+
'foo_spec.rb'
|
61
|
+
)
|
62
|
+
expect(cop.offenses).to be_empty
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does not complain for before/after :example' do
|
66
|
+
inspect_source(
|
67
|
+
cop,
|
68
|
+
[
|
69
|
+
'describe MyClass do',
|
70
|
+
' before(:example) { do_something }',
|
71
|
+
' after(:example) { do_something_else }',
|
72
|
+
'end'
|
73
|
+
],
|
74
|
+
'foo_spec.rb'
|
75
|
+
)
|
76
|
+
expect(cop.offenses).to be_empty
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'does not complain for before/after' do
|
80
|
+
inspect_source(
|
81
|
+
cop,
|
82
|
+
[
|
83
|
+
'describe MyClass do',
|
84
|
+
' before { do_something }',
|
85
|
+
' after { do_something_else }',
|
86
|
+
'end'
|
87
|
+
],
|
88
|
+
'foo_spec.rb'
|
89
|
+
)
|
90
|
+
expect(cop.offenses).to be_empty
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
describe RuboCop::Cop::RSpec::InstanceSpy do
|
2
|
+
subject(:cop) { described_class.new }
|
3
|
+
|
4
|
+
context 'when used with `have_received`' do
|
5
|
+
it 'adds an offense for an instance_double with single argument' do
|
6
|
+
expect_violation(<<-RUBY)
|
7
|
+
it do
|
8
|
+
foo = instance_double(Foo).as_null_object
|
9
|
+
^^^^^^^^^^^^^^^^^^^^ Use `instance_spy` when you check your double with `have_received`
|
10
|
+
expect(foo).to have_received(:bar)
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'adds an offense for an instance_double with multiple arguments' do
|
16
|
+
expect_violation(<<-RUBY)
|
17
|
+
it do
|
18
|
+
foo = instance_double(Foo, :name).as_null_object
|
19
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `instance_spy` when you check your double with `have_received`
|
20
|
+
expect(foo).to have_received(:bar)
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'ignores instance_double when it is not used with as_null_object' do
|
26
|
+
expect_no_violations(<<-RUBY)
|
27
|
+
it do
|
28
|
+
foo = instance_double(Foo)
|
29
|
+
expect(bar).to have_received(:bar)
|
30
|
+
end
|
31
|
+
RUBY
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when not used with `have_received`' do
|
36
|
+
it 'does not add an offence' do
|
37
|
+
expect_no_violations(<<-RUBY)
|
38
|
+
it do
|
39
|
+
foo = instance_double(Foo).as_null_object
|
40
|
+
expect(bar).to have_received(:bar)
|
41
|
+
end
|
42
|
+
RUBY
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
original = <<-RUBY
|
47
|
+
it do
|
48
|
+
foo = instance_double(Foo, :name).as_null_object
|
49
|
+
expect(foo).to have_received(:bar)
|
50
|
+
end
|
51
|
+
RUBY
|
52
|
+
corrected = <<-RUBY
|
53
|
+
it do
|
54
|
+
foo = instance_spy(Foo, :name)
|
55
|
+
expect(foo).to have_received(:bar)
|
56
|
+
end
|
57
|
+
RUBY
|
58
|
+
|
59
|
+
include_examples 'autocorrect', original, corrected
|
60
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-02-
|
13
|
+
date: 2017-02-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -147,6 +147,7 @@ files:
|
|
147
147
|
- lib/rubocop/cop/rspec/any_instance.rb
|
148
148
|
- lib/rubocop/cop/rspec/around_block.rb
|
149
149
|
- lib/rubocop/cop/rspec/be_eql.rb
|
150
|
+
- lib/rubocop/cop/rspec/before_after_all.rb
|
150
151
|
- lib/rubocop/cop/rspec/cop.rb
|
151
152
|
- lib/rubocop/cop/rspec/describe_class.rb
|
152
153
|
- lib/rubocop/cop/rspec/describe_method.rb
|
@@ -160,6 +161,7 @@ files:
|
|
160
161
|
- lib/rubocop/cop/rspec/focus.rb
|
161
162
|
- lib/rubocop/cop/rspec/hook_argument.rb
|
162
163
|
- lib/rubocop/cop/rspec/implicit_expect.rb
|
164
|
+
- lib/rubocop/cop/rspec/instance_spy.rb
|
163
165
|
- lib/rubocop/cop/rspec/instance_variable.rb
|
164
166
|
- lib/rubocop/cop/rspec/leading_subject.rb
|
165
167
|
- lib/rubocop/cop/rspec/let_setup.rb
|
@@ -199,6 +201,7 @@ files:
|
|
199
201
|
- spec/rubocop/cop/rspec/any_instance_spec.rb
|
200
202
|
- spec/rubocop/cop/rspec/around_block_spec.rb
|
201
203
|
- spec/rubocop/cop/rspec/be_eql_spec.rb
|
204
|
+
- spec/rubocop/cop/rspec/before_after_all_spec.rb
|
202
205
|
- spec/rubocop/cop/rspec/cop_spec.rb
|
203
206
|
- spec/rubocop/cop/rspec/describe_class_spec.rb
|
204
207
|
- spec/rubocop/cop/rspec/describe_method_spec.rb
|
@@ -212,6 +215,7 @@ files:
|
|
212
215
|
- spec/rubocop/cop/rspec/focus_spec.rb
|
213
216
|
- spec/rubocop/cop/rspec/hook_argument_spec.rb
|
214
217
|
- spec/rubocop/cop/rspec/implicit_expect_spec.rb
|
218
|
+
- spec/rubocop/cop/rspec/instance_spy_spec.rb
|
215
219
|
- spec/rubocop/cop/rspec/instance_variable_spec.rb
|
216
220
|
- spec/rubocop/cop/rspec/leading_subject_spec.rb
|
217
221
|
- spec/rubocop/cop/rspec/let_setup_spec.rb
|
@@ -273,6 +277,7 @@ test_files:
|
|
273
277
|
- spec/rubocop/cop/rspec/any_instance_spec.rb
|
274
278
|
- spec/rubocop/cop/rspec/around_block_spec.rb
|
275
279
|
- spec/rubocop/cop/rspec/be_eql_spec.rb
|
280
|
+
- spec/rubocop/cop/rspec/before_after_all_spec.rb
|
276
281
|
- spec/rubocop/cop/rspec/cop_spec.rb
|
277
282
|
- spec/rubocop/cop/rspec/describe_class_spec.rb
|
278
283
|
- spec/rubocop/cop/rspec/describe_method_spec.rb
|
@@ -286,6 +291,7 @@ test_files:
|
|
286
291
|
- spec/rubocop/cop/rspec/focus_spec.rb
|
287
292
|
- spec/rubocop/cop/rspec/hook_argument_spec.rb
|
288
293
|
- spec/rubocop/cop/rspec/implicit_expect_spec.rb
|
294
|
+
- spec/rubocop/cop/rspec/instance_spy_spec.rb
|
289
295
|
- spec/rubocop/cop/rspec/instance_variable_spec.rb
|
290
296
|
- spec/rubocop/cop/rspec/leading_subject_spec.rb
|
291
297
|
- spec/rubocop/cop/rspec/let_setup_spec.rb
|