Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CountAsOne config option to RSpec/ExampleLength #1139

Merged
merged 1 commit into from Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,8 @@
* Allow `RSpec/ContextWording` to accept multi-word prefixes. ([@hosamaly][])
* Drop support for ruby 2.4. ([@bquorning][])

* Add `CountAsOne` configuration option to `RSpec/ExampleLength`. ([@stephannv][])

## 2.2.0 (2021-02-02)

* Fix `HooksBeforeExamples`, `LeadingSubject`, `LetBeforeExamples` and `ScatteredLet` autocorrection to take into account inline comments and comments immediately before the moved node. ([@Darhazer][])
Expand Down Expand Up @@ -607,3 +609,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
[@ahukkanen]: https://github.com/ahukkanen
[@dvandersluis]: https://github.com/dvandersluis
[@hosamaly]: https://github.com/hosamaly
[@stephannv]: https://github.com/stephannv
2 changes: 2 additions & 0 deletions config/default.yml
Expand Up @@ -253,7 +253,9 @@ RSpec/ExampleLength:
Description: Checks for long examples.
Enabled: true
Max: 5
CountAsOne: []
VersionAdded: '1.5'
VersionChanged: '2.3'
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength

RSpec/ExampleWithoutDescription:
Expand Down
31 changes: 30 additions & 1 deletion docs/modules/ROOT/pages/cops_rspec.adoc
Expand Up @@ -1051,7 +1051,7 @@ let(:foo) { bar }
| Yes
| No
| 1.5
| -
| 2.3
|===

Checks for long examples.
Expand All @@ -1060,6 +1060,10 @@ A long example is usually more difficult to understand. Consider
extracting out some behaviour, e.g. with a `let` block, or a helper
method.

You can set literals you want to fold with `CountAsOne`.
Available are: 'array', 'hash', and 'heredoc'. Each literal
will be counted as one line regardless of its actual size.

=== Examples

[source,ruby]
Expand All @@ -1081,6 +1085,27 @@ it do
end
----

==== CountAsOne: ['array', 'heredoc']

[source,ruby]
----
it do
array = [ # +1
1,
2
]

hash = { # +3
key: 'value'
}

msg = <<~HEREDOC # +1
Heredoc
content.
HEREDOC
end # 5 points
----

=== Configurable attributes

|===
Expand All @@ -1089,6 +1114,10 @@ end
| Max
| `5`
| Integer

| CountAsOne
| `[]`
| Array
|===

=== References
Expand Down
38 changes: 26 additions & 12 deletions lib/rubocop/cop/rspec/example_length.rb
Expand Up @@ -25,29 +25,43 @@ module RSpec
# result = service.call
# expect(result).to be(true)
# end
#
# You can set literals you want to fold with `CountAsOne`.
# Available are: 'array', 'hash', and 'heredoc'. Each literal
# will be counted as one line regardless of its actual size.
#
# @example CountAsOne: ['array', 'heredoc']
#
# it do
# array = [ # +1
# 1,
# 2
# ]
#
# hash = { # +3
# key: 'value'
# }
#
# msg = <<~HEREDOC # +1
# Heredoc
# content.
# HEREDOC
# end # 5 points
class ExampleLength < Base
include CodeLength

MSG = 'Example has too many lines [%<total>d/%<max>d].'
LABEL = 'Example'

def on_block(node)
return unless example?(node)

length = code_length(node)

return unless length > max_length

add_offense(node, message: message(length))
check_code_length(node)
end

private

def code_length(node)
node.source.lines[1..-2].count { |line| !irrelevant_line(line) }
end

def message(length)
format(MSG, total: length, max: max_length)
def cop_label
LABEL
end
end
end
Expand Down
26 changes: 24 additions & 2 deletions spec/rubocop/cop/rspec/example_length_spec.rb
Expand Up @@ -46,7 +46,7 @@
it 'flags the example' do
expect_offense(<<-RUBY)
it do
^^^^^ Example has too many lines [4/3].
^^^^^ Example has too many lines. [4/3]
line 1
line 2
line 3
Expand All @@ -64,7 +64,7 @@
it 'flags the example' do
expect_offense(<<-RUBY)
it do
^^^^^ Example has too many lines [4/3].
^^^^^ Example has too many lines. [4/3]
line 1
line 2
# comment
Expand All @@ -73,4 +73,26 @@
RUBY
end
end

context 'when `CountAsOne` is not empty' do
before { cop_config['CountAsOne'] = ['array'] }

it 'folds array into one line' do
expect_no_offenses(<<~RUBY)
it do
a = 1
a = [
2,
3,
4,
5,
6,
7,
8,
9
]
end
RUBY
end
end
end