rubocop-rspec 1.0.rc2 → 1.0.rc3
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 +5 -0
- data/README.md +41 -19
- data/Rakefile +1 -1
- data/lib/rubocop-rspec.rb +8 -8
- data/lib/rubocop/cop/rspec/describe_class.rb +30 -0
- data/lib/rubocop/cop/rspec/describe_method.rb +37 -0
- data/lib/rubocop/cop/rspec/described_class.rb +58 -0
- data/lib/rubocop/cop/rspec/example_wording.rb +35 -0
- data/lib/rubocop/cop/rspec/file_name.rb +71 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +41 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +37 -0
- data/lib/rubocop/rspec/inject.rb +1 -1
- data/lib/rubocop/rspec/top_level_describe.rb +1 -1
- data/lib/rubocop/rspec/version.rb +2 -2
- data/rubocop-rspec.gemspec +2 -2
- data/spec/project_spec.rb +6 -5
- data/spec/rubocop/cop/{rspec_describe_class_spec.rb → rspec/describe_class_spec.rb} +1 -1
- data/spec/rubocop/cop/{rspec_describe_method_spec.rb → rspec/describe_method_spec.rb} +1 -1
- data/spec/rubocop/cop/{rspec_described_class_spec.rb → rspec/described_class_spec.rb} +1 -1
- data/spec/rubocop/cop/{rspec_example_wording_spec.rb → rspec/example_wording_spec.rb} +1 -1
- data/spec/rubocop/cop/{rspec_file_name_spec.rb → rspec/file_name_spec.rb} +10 -2
- data/spec/rubocop/cop/{rspec_instance_variable_spec.rb → rspec/instance_variable_spec.rb} +1 -1
- data/spec/rubocop/cop/{rspec_multiple_describes_spec.rb → rspec/multiple_describes_spec.rb} +1 -1
- data/spec/spec_helper.rb +3 -3
- metadata +42 -41
- data/lib/rubocop/cop/rspec_describe_class.rb +0 -28
- data/lib/rubocop/cop/rspec_describe_method.rb +0 -35
- data/lib/rubocop/cop/rspec_described_class.rb +0 -56
- data/lib/rubocop/cop/rspec_example_wording.rb +0 -33
- data/lib/rubocop/cop/rspec_file_name.rb +0 -54
- data/lib/rubocop/cop/rspec_instance_variable.rb +0 -39
- data/lib/rubocop/cop/rspec_multiple_describes.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bed7dbb7d971920ade6ba9925fbb552b01e79d44
|
4
|
+
data.tar.gz: 377e58808853d26bb9a0abdc5a8ceb0e7d613ca0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 281eb6abf3b67f2be3bf7ca2ce5f78ed088efec528a91d0a3d404fd7574eea928ada8425d56bf52617ab66af235122762c0fcbbe4c08f039edbbd9b65aee3f16
|
7
|
+
data.tar.gz: fbcc740631f20a639309ac9b96fa060b1d801ff59d117033e16d0a2a2b9e2e51619e53fbeabbea647aa7efeb4b43953ea704495c26ffd6d42d0882766ccfddea
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
RuboCop RSpec
|
2
|
-
=============
|
1
|
+
# RuboCop RSpec
|
3
2
|
|
4
3
|
[](https://rubygems.org/gems/rubocop-rspec)
|
5
4
|
[](https://gemnasium.com/nevir/rubocop-rspec)
|
@@ -11,46 +10,69 @@ RSpec-specific analysis for your projects, as an extension to
|
|
11
10
|
[RuboCop](https://github.com/bbatsov/rubocop).
|
12
11
|
|
13
12
|
|
14
|
-
|
15
|
-
-----
|
13
|
+
## Installation
|
16
14
|
|
17
|
-
|
15
|
+
Just install the `rubocop-rspec` gem
|
16
|
+
|
17
|
+
```bash
|
18
|
+
gem install rubocop-rspec
|
19
|
+
```
|
20
|
+
|
21
|
+
or if you use bundler put this in your `Gemfile`
|
22
|
+
|
23
|
+
```
|
24
|
+
gem 'rubocop-rspec'
|
25
|
+
```
|
26
|
+
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
You need to tell RuboCop to load the RSpec extension. There are three
|
31
|
+
ways to do this:
|
32
|
+
|
33
|
+
### RuboCop configuration file
|
34
|
+
|
35
|
+
Put this into you `.rubocop.yml`.
|
36
|
+
|
37
|
+
```
|
38
|
+
require: rubocop-rspec
|
39
|
+
```
|
40
|
+
|
41
|
+
Now you can run `rubocop` and it will autmaticly load the RuboCop RSpec
|
42
|
+
cops together with the standard cops.
|
43
|
+
|
44
|
+
### Command line
|
18
45
|
|
19
46
|
```bash
|
20
47
|
rubocop --require rubocop-rspec
|
21
48
|
```
|
22
49
|
|
23
|
-
|
50
|
+
### Rake task
|
24
51
|
|
25
52
|
```ruby
|
26
|
-
|
53
|
+
RuboCop::RakeTask.new do |task|
|
27
54
|
task.requires << 'rubocop-rspec'
|
28
55
|
end
|
29
56
|
```
|
30
57
|
|
31
58
|
|
32
|
-
The Cops
|
33
|
-
--------
|
34
|
-
|
35
|
-
**WARNING: Cop names are under flux and will likely change in the near future.**
|
36
|
-
We're hoping to
|
37
|
-
[introduce namespaces](https://github.com/bbatsov/rubocop/issues/1097) into the mix.
|
59
|
+
## The Cops
|
38
60
|
|
39
|
-
All cops are located under
|
61
|
+
All cops are located under
|
62
|
+
[`lib/rubocop/cop/spec`](lib/rubocop/cop/rspec), and contain
|
40
63
|
examples/documentation.
|
41
64
|
|
42
|
-
In your `.rubocop.yml`, you may treat the RSpec cops just like any other
|
43
|
-
For example:
|
65
|
+
In your `.rubocop.yml`, you may treat the RSpec cops just like any other
|
66
|
+
cop. For example:
|
44
67
|
|
45
68
|
```yaml
|
46
|
-
|
69
|
+
RSpec/FileName:
|
47
70
|
Exclude:
|
48
71
|
- spec/my_poorly_named_spec_file.rb
|
49
72
|
```
|
50
73
|
|
51
74
|
|
52
|
-
License
|
53
|
-
-------
|
75
|
+
## License
|
54
76
|
|
55
77
|
`rubocop-rspec` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for
|
56
78
|
the full text.
|
data/Rakefile
CHANGED
data/lib/rubocop-rspec.rb
CHANGED
@@ -6,13 +6,13 @@ require 'rubocop/rspec/version'
|
|
6
6
|
require 'rubocop/rspec/inject'
|
7
7
|
require 'rubocop/rspec/top_level_describe'
|
8
8
|
|
9
|
-
|
9
|
+
RuboCop::RSpec::Inject.defaults!
|
10
10
|
|
11
11
|
# cops
|
12
|
-
require 'rubocop/cop/
|
13
|
-
require 'rubocop/cop/
|
14
|
-
require 'rubocop/cop/
|
15
|
-
require 'rubocop/cop/
|
16
|
-
require 'rubocop/cop/
|
17
|
-
require 'rubocop/cop/
|
18
|
-
require 'rubocop/cop/
|
12
|
+
require 'rubocop/cop/rspec/describe_class'
|
13
|
+
require 'rubocop/cop/rspec/describe_method'
|
14
|
+
require 'rubocop/cop/rspec/described_class'
|
15
|
+
require 'rubocop/cop/rspec/example_wording'
|
16
|
+
require 'rubocop/cop/rspec/file_name'
|
17
|
+
require 'rubocop/cop/rspec/instance_variable'
|
18
|
+
require 'rubocop/cop/rspec/multiple_describes'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Check that the first argument to the top level describe is the tested
|
7
|
+
# class or module.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# describe 'Do something' do
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# describe TestedClass do
|
16
|
+
# end
|
17
|
+
class DescribeClass < Cop
|
18
|
+
include RuboCop::RSpec::TopLevelDescribe
|
19
|
+
|
20
|
+
MESSAGE = 'The first argument to describe should be the class or ' \
|
21
|
+
'module being tested.'
|
22
|
+
|
23
|
+
def on_top_level_describe(_node, args)
|
24
|
+
return if args.first && args.first.type == :const
|
25
|
+
add_offense(args.first, :expression, MESSAGE)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that the second argument to the top level describe is the tested
|
7
|
+
# method name.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# describe MyClass, 'do something' do
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# describe MyClass, '#my_instance_method' do
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# describe MyClass, '.my_class_method' do
|
19
|
+
# end
|
20
|
+
class DescribeMethod < Cop
|
21
|
+
include RuboCop::RSpec::TopLevelDescribe
|
22
|
+
|
23
|
+
MESSAGE = 'The second argument to describe should be the method ' \
|
24
|
+
"being tested. '#instance' or '.class'"
|
25
|
+
METHOD_STRING_MATCHER = /^[\#\.].+/
|
26
|
+
|
27
|
+
def on_top_level_describe(_node, args)
|
28
|
+
second_arg = args[1]
|
29
|
+
return unless second_arg
|
30
|
+
return if METHOD_STRING_MATCHER =~ second_arg.children.first
|
31
|
+
|
32
|
+
add_offense(second_arg, :expression, MESSAGE)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# If the first argument of describe is a class, the class is exposed to
|
7
|
+
# each example via described_class - this should be used instead of
|
8
|
+
# repeating the class.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# describe MyClass do
|
13
|
+
# subject { MyClass.do_something }
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# describe MyClass do
|
18
|
+
# subject { described_class.do_something }
|
19
|
+
# end
|
20
|
+
class DescribedClass < Cop
|
21
|
+
include RuboCop::RSpec::TopLevelDescribe
|
22
|
+
|
23
|
+
MESSAGE = 'Use `described_class` instead of `%s`'
|
24
|
+
|
25
|
+
def on_block(node)
|
26
|
+
method, _args, body = *node
|
27
|
+
return unless top_level_describe?(method)
|
28
|
+
|
29
|
+
_receiver, method_name, object = *method
|
30
|
+
return unless method_name == :describe
|
31
|
+
return unless object && object.type == :const
|
32
|
+
|
33
|
+
inspect_children(body, object)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def inspect_children(node, object)
|
39
|
+
return unless node.is_a? Parser::AST::Node
|
40
|
+
return if scope_change?(node) || node.type == :const
|
41
|
+
|
42
|
+
node.children.each do |child|
|
43
|
+
if child == object
|
44
|
+
name = object.loc.expression.source
|
45
|
+
add_offense(child, :expression, format(MESSAGE, name))
|
46
|
+
break
|
47
|
+
end
|
48
|
+
inspect_children(child, object)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def scope_change?(node)
|
53
|
+
[:def, :class, :module].include?(node.type)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Do not use should when describing your tests.
|
7
|
+
# see: http://betterspecs.org/#should
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# it 'should find nothing' do
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# it 'finds nothing' do
|
16
|
+
# end
|
17
|
+
class ExampleWording < Cop
|
18
|
+
MSG = 'Do not use should when describing your tests.'
|
19
|
+
|
20
|
+
def on_block(node)
|
21
|
+
method, _, _ = *node
|
22
|
+
_, method_name, *args = *method
|
23
|
+
|
24
|
+
return unless method_name == :it
|
25
|
+
|
26
|
+
arguments = *(args.first)
|
27
|
+
message = arguments.first.to_s
|
28
|
+
return unless message.start_with?('should')
|
29
|
+
|
30
|
+
add_offense(method, :selector, MSG)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks the path of the spec file and enforces that it reflects the
|
7
|
+
# described class/module and its optionally called out method.
|
8
|
+
#
|
9
|
+
# With the configuration option `CustomTransform` modules or clases can be
|
10
|
+
# specified that should not as usual be transformed from CamelCase to
|
11
|
+
# snake_case (e.g. 'RuboCop' => 'rubocop' ).
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# my_class/method_spec.rb # describe MyClass, '#method'
|
15
|
+
# my_class_method_spec.rb # describe MyClass, '#method'
|
16
|
+
# my_class_spec.rb # describe MyClass
|
17
|
+
class FileName < Cop
|
18
|
+
include RuboCop::RSpec::TopLevelDescribe
|
19
|
+
|
20
|
+
MESSAGE = 'Spec path should end with `%s`'
|
21
|
+
METHOD_STRING_MATCHER = /^[\#\.].+/
|
22
|
+
|
23
|
+
def on_top_level_describe(node, args)
|
24
|
+
return unless single_top_level_describe?
|
25
|
+
object = const_name(args.first)
|
26
|
+
return unless object
|
27
|
+
|
28
|
+
path_matcher = matcher(object, args[1])
|
29
|
+
return if source_filename =~ regexp_from_glob(path_matcher)
|
30
|
+
|
31
|
+
add_offense(node, :expression, format(MESSAGE, path_matcher))
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def matcher(object, method)
|
37
|
+
path = File.join(parts(object))
|
38
|
+
path += '*' + method.children.first.gsub(/\W+/, '') if method
|
39
|
+
|
40
|
+
"#{path}*_spec.rb"
|
41
|
+
end
|
42
|
+
|
43
|
+
def parts(object)
|
44
|
+
object.split('::').map do |p|
|
45
|
+
custom_transform[p] || camel_to_underscore(p)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def source_filename
|
50
|
+
processed_source.buffer.name
|
51
|
+
end
|
52
|
+
|
53
|
+
def camel_to_underscore(string)
|
54
|
+
string.dup.tap do |result|
|
55
|
+
result.gsub!(/([^A-Z])([A-Z]+)/, '\\1_\\2')
|
56
|
+
result.gsub!(/([A-Z]{2,})([A-Z][^A-Z]+)/, '\\1_\\2')
|
57
|
+
result.downcase!
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def regexp_from_glob(glob)
|
62
|
+
Regexp.new(glob.gsub('.', '\\.').gsub('*', '.*') + '$')
|
63
|
+
end
|
64
|
+
|
65
|
+
def custom_transform
|
66
|
+
cop_config['CustomTransform'] || []
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# When you have to assign a variable instead of using an instance
|
7
|
+
# variable, use let.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# describe MyClass do
|
12
|
+
# before { @foo = [] }
|
13
|
+
# it { expect(@foo).to be_emtpy }
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# describe MyClass do
|
18
|
+
# let(:foo) { [] }
|
19
|
+
# it { expect(foo).to be_emtpy }
|
20
|
+
# end
|
21
|
+
class InstanceVariable < Cop
|
22
|
+
MESSAGE = 'Use `let` instead of an instance variable'
|
23
|
+
EXAMPLE_GROUP_METHODS = [
|
24
|
+
:example_group, :describe, :context, :xdescribe, :xcontext,
|
25
|
+
:fdescribe, :fcontext, :shared_examples, :shared_context,
|
26
|
+
:share_examples_for, :shared_examples_for, :feature
|
27
|
+
]
|
28
|
+
|
29
|
+
def on_block(node)
|
30
|
+
method, _args, _body = *node
|
31
|
+
_receiver, method_name, _object = *method
|
32
|
+
@in_spec = true if EXAMPLE_GROUP_METHODS.include?(method_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_ivar(node)
|
36
|
+
add_offense(node, :expression, MESSAGE) if @in_spec
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for multiple top level describes. They should be nested if it is
|
7
|
+
# for the same class or module or seperated into different files.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# describe MyClass, '.do_someting' do
|
12
|
+
# end
|
13
|
+
# describe MyClass, '.do_someting_else' do
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# #good
|
17
|
+
# describe MyClass
|
18
|
+
# describe '.do_someting' do
|
19
|
+
# end
|
20
|
+
# describe '.do_someting_else' do
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
class MultipleDescribes < Cop
|
24
|
+
include RuboCop::RSpec::TopLevelDescribe
|
25
|
+
|
26
|
+
MESSAGE = 'Do not use multiple top level describes - try to nest them.'
|
27
|
+
|
28
|
+
def on_top_level_describe(node, _args)
|
29
|
+
return if single_top_level_describe?
|
30
|
+
return unless top_level_nodes.first == node
|
31
|
+
|
32
|
+
add_offense(node, :expression, MESSAGE)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/rubocop/rspec/inject.rb
CHANGED
data/rubocop-rspec.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.email = ['ian@nevir.net', 'git@nilsgemeinhardt.de']
|
16
16
|
spec.licenses = ['MIT']
|
17
17
|
|
18
|
-
spec.version =
|
18
|
+
spec.version = RuboCop::RSpec::Version::STRING
|
19
19
|
spec.platform = Gem::Platform::RUBY
|
20
20
|
spec.required_ruby_version = '>= 1.9.2'
|
21
21
|
|
@@ -30,5 +30,5 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.test_files = spec.files.grep(/^spec\//)
|
31
31
|
spec.extra_rdoc_files = ['MIT-LICENSE.md', 'README.md']
|
32
32
|
|
33
|
-
spec.add_runtime_dependency('rubocop', '~> 0.
|
33
|
+
spec.add_runtime_dependency('rubocop', '~> 0.23', '>= 0.23')
|
34
34
|
end
|
data/spec/project_spec.rb
CHANGED
@@ -2,20 +2,21 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'RuboCop Project' do # rubocop:disable
|
5
|
+
describe 'RuboCop Project' do # rubocop:disable RSpec/DescribeClass
|
6
6
|
describe 'default configuration file' do
|
7
7
|
let(:cop_names) do
|
8
8
|
Dir.glob(File.join(File.dirname(__FILE__), '..', 'lib', 'rubocop', 'cop',
|
9
|
-
'*.rb'))
|
9
|
+
'rspec', '*.rb'))
|
10
10
|
.map do |file|
|
11
|
-
File.basename(file, '.rb')
|
11
|
+
cop_name = File.basename(file, '.rb')
|
12
12
|
.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase }
|
13
|
-
|
13
|
+
|
14
|
+
"RSpec/#{cop_name}"
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
18
|
subject(:default_config) do
|
18
|
-
|
19
|
+
RuboCop::ConfigLoader.load_file('config/default.yml')
|
19
20
|
end
|
20
21
|
|
21
22
|
it 'has configuration for all cops' do
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe
|
6
|
-
subject(:cop) { described_class.new }
|
5
|
+
describe RuboCop::Cop::RSpec::FileName, :config do
|
6
|
+
subject(:cop) { described_class.new(config) }
|
7
|
+
let(:cop_config) { { 'CustomTransform' => { 'FooFoo' => 'foofoo' } } }
|
7
8
|
|
8
9
|
it 'checks the path' do
|
9
10
|
inspect_source(cop,
|
@@ -140,4 +141,11 @@ describe Rubocop::Cop::RSpecFileName do
|
|
140
141
|
'my_class/spaceship_operator_spec.rb')
|
141
142
|
expect(cop.offenses).to be_empty
|
142
143
|
end
|
144
|
+
|
145
|
+
it 'respects custom module name transformation' do
|
146
|
+
inspect_source(cop,
|
147
|
+
["describe FooFoo::Some::Class, '#bar' do; end"],
|
148
|
+
'foofoo/some/class/bar_spec.rb')
|
149
|
+
expect(cop.offenses).to be_empty
|
150
|
+
end
|
143
151
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -15,12 +15,12 @@ require 'rubocop-rspec'
|
|
15
15
|
def parse_source(source, file = nil)
|
16
16
|
source = source.join($RS) if source.is_a?(Array)
|
17
17
|
if file.is_a? String
|
18
|
-
|
18
|
+
RuboCop::SourceParser.parse(source, file)
|
19
19
|
elsif file
|
20
20
|
file.write(source)
|
21
21
|
file.rewind
|
22
|
-
|
22
|
+
RuboCop::SourceParser.parse(source, file.path)
|
23
23
|
else
|
24
|
-
|
24
|
+
RuboCop::SourceParser.parse(source)
|
25
25
|
end
|
26
26
|
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.0.
|
4
|
+
version: 1.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian MacLeod
|
@@ -9,28 +9,28 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubocop
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '0.
|
21
|
-
- -
|
20
|
+
version: '0.23'
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: '0.
|
23
|
+
version: '0.23'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - ~>
|
28
|
+
- - "~>"
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version: '0.
|
31
|
-
- -
|
30
|
+
version: '0.23'
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.23'
|
34
34
|
description: |2
|
35
35
|
Code style checking for RSpec files.
|
36
36
|
A plugin for the RuboCop code style enforcing & linting tool.
|
@@ -43,32 +43,32 @@ extra_rdoc_files:
|
|
43
43
|
- MIT-LICENSE.md
|
44
44
|
- README.md
|
45
45
|
files:
|
46
|
-
-
|
47
|
-
-
|
48
|
-
-
|
49
|
-
-
|
50
|
-
-
|
51
|
-
- lib/rubocop
|
52
|
-
- lib/rubocop/cop/
|
46
|
+
- CHANGELOG.md
|
47
|
+
- Gemfile
|
48
|
+
- MIT-LICENSE.md
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- lib/rubocop-rspec.rb
|
52
|
+
- lib/rubocop/cop/rspec/describe_class.rb
|
53
|
+
- lib/rubocop/cop/rspec/describe_method.rb
|
54
|
+
- lib/rubocop/cop/rspec/described_class.rb
|
55
|
+
- lib/rubocop/cop/rspec/example_wording.rb
|
56
|
+
- lib/rubocop/cop/rspec/file_name.rb
|
57
|
+
- lib/rubocop/cop/rspec/instance_variable.rb
|
58
|
+
- lib/rubocop/cop/rspec/multiple_describes.rb
|
53
59
|
- lib/rubocop/rspec/inject.rb
|
54
60
|
- lib/rubocop/rspec/top_level_describe.rb
|
55
61
|
- lib/rubocop/rspec/version.rb
|
56
|
-
-
|
62
|
+
- rubocop-rspec.gemspec
|
57
63
|
- spec/project_spec.rb
|
58
|
-
- spec/rubocop/cop/
|
59
|
-
- spec/rubocop/cop/
|
60
|
-
- spec/rubocop/cop/
|
61
|
-
- spec/rubocop/cop/
|
62
|
-
- spec/rubocop/cop/
|
63
|
-
- spec/rubocop/cop/
|
64
|
-
- spec/rubocop/cop/
|
64
|
+
- spec/rubocop/cop/rspec/describe_class_spec.rb
|
65
|
+
- spec/rubocop/cop/rspec/describe_method_spec.rb
|
66
|
+
- spec/rubocop/cop/rspec/described_class_spec.rb
|
67
|
+
- spec/rubocop/cop/rspec/example_wording_spec.rb
|
68
|
+
- spec/rubocop/cop/rspec/file_name_spec.rb
|
69
|
+
- spec/rubocop/cop/rspec/instance_variable_spec.rb
|
70
|
+
- spec/rubocop/cop/rspec/multiple_describes_spec.rb
|
65
71
|
- spec/spec_helper.rb
|
66
|
-
- CHANGELOG.md
|
67
|
-
- MIT-LICENSE.md
|
68
|
-
- README.md
|
69
|
-
- rubocop-rspec.gemspec
|
70
|
-
- Gemfile
|
71
|
-
- Rakefile
|
72
72
|
homepage: http://github.com/nevir/rubocop-rspec
|
73
73
|
licenses:
|
74
74
|
- MIT
|
@@ -79,27 +79,28 @@ require_paths:
|
|
79
79
|
- lib
|
80
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
|
-
- -
|
82
|
+
- - ">="
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: 1.9.2
|
85
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 1.3.1
|
90
90
|
requirements: []
|
91
91
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.0
|
92
|
+
rubygems_version: 2.2.0
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: Code style checking for RSpec files
|
96
96
|
test_files:
|
97
97
|
- spec/project_spec.rb
|
98
|
-
- spec/rubocop/cop/
|
99
|
-
- spec/rubocop/cop/
|
100
|
-
- spec/rubocop/cop/
|
101
|
-
- spec/rubocop/cop/
|
102
|
-
- spec/rubocop/cop/
|
103
|
-
- spec/rubocop/cop/
|
104
|
-
- spec/rubocop/cop/
|
98
|
+
- spec/rubocop/cop/rspec/describe_class_spec.rb
|
99
|
+
- spec/rubocop/cop/rspec/describe_method_spec.rb
|
100
|
+
- spec/rubocop/cop/rspec/described_class_spec.rb
|
101
|
+
- spec/rubocop/cop/rspec/example_wording_spec.rb
|
102
|
+
- spec/rubocop/cop/rspec/file_name_spec.rb
|
103
|
+
- spec/rubocop/cop/rspec/instance_variable_spec.rb
|
104
|
+
- spec/rubocop/cop/rspec/multiple_describes_spec.rb
|
105
105
|
- spec/spec_helper.rb
|
106
|
+
has_rdoc:
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# Check that the first argument to the top level describe is the tested
|
6
|
-
# class or module.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# describe 'Do something' do
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# # good
|
14
|
-
# describe TestedClass do
|
15
|
-
# end
|
16
|
-
class RSpecDescribeClass < Cop
|
17
|
-
include RSpec::TopLevelDescribe
|
18
|
-
|
19
|
-
MESSAGE = 'The first argument to describe should be the class or ' \
|
20
|
-
'module being tested.'
|
21
|
-
|
22
|
-
def on_top_level_describe(_node, args)
|
23
|
-
return if args.first && args.first.type == :const
|
24
|
-
add_offense(args.first, :expression, MESSAGE)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# Checks that the second argument to the top level describe is the tested
|
6
|
-
# method name.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# describe MyClass, 'do something' do
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# # good
|
14
|
-
# describe MyClass, '#my_instance_method' do
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# describe MyClass, '.my_class_method' do
|
18
|
-
# end
|
19
|
-
class RSpecDescribeMethod < Cop
|
20
|
-
include RSpec::TopLevelDescribe
|
21
|
-
|
22
|
-
MESSAGE = 'The second argument to describe should be the method being ' \
|
23
|
-
"tested. '#instance' or '.class'"
|
24
|
-
METHOD_STRING_MATCHER = /^[\#\.].+/
|
25
|
-
|
26
|
-
def on_top_level_describe(_node, args)
|
27
|
-
second_arg = args[1]
|
28
|
-
return unless second_arg
|
29
|
-
return if METHOD_STRING_MATCHER =~ second_arg.children.first
|
30
|
-
|
31
|
-
add_offense(second_arg, :expression, MESSAGE)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# If the first argument of describe is a class, the class is exposed to
|
6
|
-
# each example via described_class - this should be used instead of
|
7
|
-
# repeating the class.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# # bad
|
11
|
-
# describe MyClass do
|
12
|
-
# subject { MyClass.do_something }
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# # good
|
16
|
-
# describe MyClass do
|
17
|
-
# subject { described_class.do_something }
|
18
|
-
# end
|
19
|
-
class RSpecDescribedClass < Cop
|
20
|
-
include RSpec::TopLevelDescribe
|
21
|
-
|
22
|
-
MESSAGE = 'Use `described_class` instead of `%s`'
|
23
|
-
|
24
|
-
def on_block(node)
|
25
|
-
method, _args, body = *node
|
26
|
-
return unless top_level_describe?(method)
|
27
|
-
|
28
|
-
_receiver, method_name, object = *method
|
29
|
-
return unless method_name == :describe
|
30
|
-
return unless object && object.type == :const
|
31
|
-
|
32
|
-
inspect_children(body, object)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def inspect_children(node, object)
|
38
|
-
return unless node.is_a? Parser::AST::Node
|
39
|
-
return if scope_change?(node) || node.type == :const
|
40
|
-
|
41
|
-
node.children.each do |child|
|
42
|
-
if child == object
|
43
|
-
name = object.loc.expression.source
|
44
|
-
add_offense(child, :expression, format(MESSAGE, name))
|
45
|
-
break
|
46
|
-
end
|
47
|
-
inspect_children(child, object)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def scope_change?(node)
|
52
|
-
[:def, :class, :module].include?(node.type)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# Do not use should when describing your tests.
|
6
|
-
# see: http://betterspecs.org/#should
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# it 'should find nothing' do
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# # good
|
14
|
-
# it 'finds nothing' do
|
15
|
-
# end
|
16
|
-
class RSpecExampleWording < Cop
|
17
|
-
MSG = 'Do not use should when describing your tests.'
|
18
|
-
|
19
|
-
def on_block(node)
|
20
|
-
method, _, _ = *node
|
21
|
-
_, method_name, *args = *method
|
22
|
-
|
23
|
-
return unless method_name == :it
|
24
|
-
|
25
|
-
arguments = *(args.first)
|
26
|
-
message = arguments.first.to_s
|
27
|
-
return unless message.start_with?('should')
|
28
|
-
|
29
|
-
add_offense(method, :selector, MSG)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# Checks the path of the spec file and enforces that it reflects the
|
6
|
-
# described class/module and its optionally called out method.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# my_class/method_spec.rb # describe MyClass, '#method'
|
10
|
-
# my_class_spec.rb # describe MyClass
|
11
|
-
class RSpecFileName < Cop
|
12
|
-
include RSpec::TopLevelDescribe
|
13
|
-
|
14
|
-
MESSAGE = 'Spec path should end with `%s`'
|
15
|
-
METHOD_STRING_MATCHER = /^[\#\.].+/
|
16
|
-
|
17
|
-
def on_top_level_describe(node, args)
|
18
|
-
return unless single_top_level_describe?
|
19
|
-
object = const_name(args.first)
|
20
|
-
return unless object
|
21
|
-
|
22
|
-
path_matcher = matcher(object, args[1])
|
23
|
-
return if source_filename =~ regexp_from_glob(path_matcher)
|
24
|
-
|
25
|
-
add_offense(node, :expression, format(MESSAGE, path_matcher))
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def matcher(object, method)
|
31
|
-
path = File.join(object.split('::').map { |p| camel_to_underscore(p) })
|
32
|
-
path += '*' + method.children.first.gsub(/\W+/, '') if method
|
33
|
-
|
34
|
-
"#{path}*_spec.rb"
|
35
|
-
end
|
36
|
-
|
37
|
-
def source_filename
|
38
|
-
processed_source.buffer.name
|
39
|
-
end
|
40
|
-
|
41
|
-
def camel_to_underscore(string)
|
42
|
-
string.dup.tap do |result|
|
43
|
-
result.gsub!(/([^A-Z])([A-Z]+)/, '\\1_\\2')
|
44
|
-
result.gsub!(/([A-Z]{2,})([A-Z][^A-Z]+)/, '\\1_\\2')
|
45
|
-
result.downcase!
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def regexp_from_glob(glob)
|
50
|
-
Regexp.new(glob.gsub('.', '\\.').gsub('*', '.*') + '$')
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# When you have to assign a variable instead of using an instance variable,
|
6
|
-
# use let.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# describe MyClass do
|
11
|
-
# before { @foo = [] }
|
12
|
-
# it { expect(@foo).to be_emtpy }
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# # good
|
16
|
-
# describe MyClass do
|
17
|
-
# let(:foo) { [] }
|
18
|
-
# it { expect(foo).to be_emtpy }
|
19
|
-
# end
|
20
|
-
class RSpecInstanceVariable < Cop
|
21
|
-
MESSAGE = 'Use `let` instead of an instance variable'
|
22
|
-
EXAMPLE_GROUP_METHODS = [
|
23
|
-
:example_group, :describe, :context, :xdescribe, :xcontext, :fdescribe,
|
24
|
-
:fcontext, :shared_examples, :shared_context, :share_examples_for,
|
25
|
-
:shared_examples_for, :feature
|
26
|
-
]
|
27
|
-
|
28
|
-
def on_block(node)
|
29
|
-
method, _args, _body = *node
|
30
|
-
_receiver, method_name, _object = *method
|
31
|
-
@in_spec = true if EXAMPLE_GROUP_METHODS.include?(method_name)
|
32
|
-
end
|
33
|
-
|
34
|
-
def on_ivar(node)
|
35
|
-
add_offense(node, :expression, MESSAGE) if @in_spec
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Rubocop
|
4
|
-
module Cop
|
5
|
-
# Checks for multiple top level describes. They should be nested if it is
|
6
|
-
# for the same class or module or seperated into different files.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# describe MyClass, '.do_someting' do
|
11
|
-
# end
|
12
|
-
# describe MyClass, '.do_someting_else' do
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# #good
|
16
|
-
# describe MyClass
|
17
|
-
# describe '.do_someting' do
|
18
|
-
# end
|
19
|
-
# describe '.do_someting_else' do
|
20
|
-
# end
|
21
|
-
# end
|
22
|
-
class RSpecMultipleDescribes < Cop
|
23
|
-
include RSpec::TopLevelDescribe
|
24
|
-
|
25
|
-
MESSAGE = 'Do not use multiple top level describes - try to nest them.'
|
26
|
-
|
27
|
-
def on_top_level_describe(node, _args)
|
28
|
-
return if single_top_level_describe?
|
29
|
-
return unless top_level_nodes.first == node
|
30
|
-
|
31
|
-
add_offense(node, :expression, MESSAGE)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|