Skip to content

Commit

Permalink
Merge pull request #1350 from akrox58/FIX-1337/update_example_wording…
Browse files Browse the repository at this point in the history
…_cop_to_call_out_insufficient_descriptions

[Fix #1337] Update the cop to raise error for insufficient descriptions.
  • Loading branch information
pirj authored Oct 13, 2022
2 parents 494de00 + 31c1dd7 commit d16fb33
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Add `require_implicit` style to `RSpec/ImplicitSubject`. ([@r7kamura][])
* Fix a false positive for `RSpec/Capybara/SpecificMatcher` when `have_css("a")` without attribute. ([@ydah][])
* Update `RSpec/ExampleWording` cop to raise error for insufficient descriptions. ([@akrox58][])

## 2.13.2 (2022-09-23)

Expand Down Expand Up @@ -650,6 +651,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
[@abrom]: https://github.com/abrom
[@ahukkanen]: https://github.com/ahukkanen
[@akiomik]: https://github.com/akiomik
[@akrox58]: https://github.com/akrox58
[@AlexWayfer]: https://github.com/AlexWayfer
[@andrykonchin]: https://github.com/andrykonchin
[@andyw8]: https://github.com/andyw8
Expand Down
6 changes: 4 additions & 2 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ RSpec/ChangeByZero:
Description: Prefer negated matchers over `to change.by(0)`.
Enabled: pending
VersionAdded: '2.11'
VersionChanged: '2.13'
VersionChanged: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero
NegatedMatcher: ~

Expand Down Expand Up @@ -383,8 +383,10 @@ RSpec/ExampleWording:
have: has
HAVE: HAS
IgnoredWords: []
DisallowedExamples:
- works
VersionAdded: '1.0'
VersionChanged: '1.2'
VersionChanged: '2.13'
StyleGuide: https://rspec.rubystyle.guide/#should-in-example-docstrings
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording

Expand Down
26 changes: 24 additions & 2 deletions docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ end
| Yes
| Yes
| 2.11
| 2.13
| <<next>>
|===

Prefer negated matchers over `to change.by(0)`.
Expand Down Expand Up @@ -1534,16 +1534,21 @@ end
| Yes
| Yes
| 1.0
| 1.2
| 2.13
|===

Checks for common mistakes in example descriptions.

This cop will correct docstrings that begin with 'should' and 'it'.
This cop will also look for insufficient examples and call them out.

The autocorrect is experimental - use with care! It can be configured
with CustomTransform (e.g. have => has) and IgnoredWords (e.g. only).

Use the DisallowedExamples setting to prevent unclear or insufficient
descriptions. Please note that this config will not be treated as
case sensitive.

=== Examples

[source,ruby]
Expand All @@ -1568,6 +1573,19 @@ it 'does things' do
end
----

==== `DisallowedExamples: ['works']` (default)

[source,ruby]
----
# bad
it 'works' do
end
# good
it 'marks the task as done' do
end
----

=== Configurable attributes

|===
Expand All @@ -1580,6 +1598,10 @@ end
| IgnoredWords
| `[]`
| Array

| DisallowedExamples
| `works`
| Array
|===

=== References
Expand Down
32 changes: 32 additions & 0 deletions lib/rubocop/cop/rspec/example_wording.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ module RSpec
# Checks for common mistakes in example descriptions.
#
# This cop will correct docstrings that begin with 'should' and 'it'.
# This cop will also look for insufficient examples and call them out.
#
# @see http://betterspecs.org/#should
#
# The autocorrect is experimental - use with care! It can be configured
# with CustomTransform (e.g. have => has) and IgnoredWords (e.g. only).
#
# Use the DisallowedExamples setting to prevent unclear or insufficient
# descriptions. Please note that this config will not be treated as
# case sensitive.
#
# @example
# # bad
# it 'should find nothing' do
Expand All @@ -30,11 +35,21 @@ module RSpec
# it 'does things' do
# end
#
# @example `DisallowedExamples: ['works']` (default)
# # bad
# it 'works' do
# end
#
# # good
# it 'marks the task as done' do
# end
class ExampleWording < Base
extend AutoCorrector

MSG_SHOULD = 'Do not use should when describing your tests.'
MSG_IT = "Do not repeat 'it' when describing your tests."
MSG_INSUFFICIENT_DESCRIPTION = 'Your example description is ' \
'insufficient.'

SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze
IT_PREFIX = /\Ait /i.freeze
Expand All @@ -53,12 +68,20 @@ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
add_wording_offense(description_node, MSG_SHOULD)
elsif message.match?(IT_PREFIX)
add_wording_offense(description_node, MSG_IT)
else
check_and_handle_insufficient_examples(description_node)
end
end
end

private

def check_and_handle_insufficient_examples(description)
if insufficient_examples.include?(preprocess(text(description)))
add_wording_offense(description, MSG_INSUFFICIENT_DESCRIPTION)
end
end

def add_wording_offense(node, message)
docstring = docstring(node)

Expand Down Expand Up @@ -113,6 +136,15 @@ def custom_transform
def ignored_words
cop_config.fetch('IgnoredWords', [])
end

def insufficient_examples
examples = cop_config.fetch('DisallowedExamples', [])
examples.map! { |example| preprocess(example) }
end

def preprocess(message)
message.strip.squeeze(' ').downcase
end
end
end
end
Expand Down
61 changes: 61 additions & 0 deletions spec/rubocop/cop/rspec/example_wording_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,65 @@
end
RUBY
end

it 'flags an unclear description' do
expect_offense(<<-'RUBY')
it "works" do
^^^^^ Your example description is insufficient.
end
RUBY
end

it 'flags an unclear description despite extra spaces' do
expect_offense(<<-'RUBY')
it " works " do
^^^^^^^^^^^ Your example description is insufficient.
end
RUBY
end

it 'flags an unclear description despite uppercase and lowercase strings' do
expect_offense(<<-'RUBY')
it "WOrKs " do
^^^^^^ Your example description is insufficient.
end
RUBY
end

context 'when `DisallowedExamples: Workz`' do
let(:cop_config) { { 'DisallowedExamples' => ['Workz'] } }

it 'finds a valid sentence across two lines' do
expect_no_offenses(<<-'RUBY')
it "workz " \
"totally fine " do
end
RUBY
end

it 'finds an invalid example across two lines' do
expect_offense(<<-'RUBY')
it "workz" \
^^^^^^^^ Your example description is insufficient.
" " do
end
RUBY
end

it 'flags an unclear description' do
expect_offense(<<-'RUBY')
it "workz" do
^^^^^ Your example description is insufficient.
end
RUBY
end

it 'flags an unclear description despite uppercase and lowercase strings' do
expect_offense(<<-'RUBY')
it "WOrKz " do
^^^^^^ Your example description is insufficient.
end
RUBY
end
end
end

0 comments on commit d16fb33

Please sign in to comment.