rubocop-rspec 1.11.0 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|