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 new RSpec/UndescriptiveLiteralsDescription cop #1796

Merged
merged 1 commit into from
Apr 1, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ RSpec/ClassCheck:
Enabled: true
RSpec/ContainExactly:
Enabled: true
RSpec/UndescriptiveLiteralsDescription:
Enabled: true
RSpec/DuplicatedMetadata:
Enabled: true
RSpec/EmptyMetadata:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Master (Unreleased)

- Fix an autocorrect error for `RSpec/ExpectActual`. ([@bquorning])
- Add new `RSpec/UndescriptiveLiteralsDescription` cop. ([@ydah])

## 2.28.0 (2024-03-30)

Expand Down
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,12 @@ RSpec/SubjectStub:
StyleGuide: https://rspec.rubystyle.guide/#dont-stub-subject
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub

RSpec/UndescriptiveLiteralsDescription:
Description: Description should be descriptive.
Enabled: pending
VersionAdded: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UndescriptiveLiteralsDescription

RSpec/UnspecifiedException:
Description: Checks for a specified error in checking raised errors.
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/cops.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
* xref:cops_rspec.adoc#rspecstubbedmock[RSpec/StubbedMock]
* xref:cops_rspec.adoc#rspecsubjectdeclaration[RSpec/SubjectDeclaration]
* xref:cops_rspec.adoc#rspecsubjectstub[RSpec/SubjectStub]
* xref:cops_rspec.adoc#rspecundescriptiveliteralsdescription[RSpec/UndescriptiveLiteralsDescription]
* xref:cops_rspec.adoc#rspecunspecifiedexception[RSpec/UnspecifiedException]
* xref:cops_rspec.adoc#rspecvariabledefinition[RSpec/VariableDefinition]
* xref:cops_rspec.adoc#rspecvariablename[RSpec/VariableName]
Expand Down
61 changes: 61 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5617,6 +5617,67 @@ end
* https://robots.thoughtbot.com/don-t-stub-the-system-under-test
* https://penelope.zone/2015/12/27/introducing-rspec-smells-and-where-to-find-them.html#smell-1-stubjec

== RSpec/UndescriptiveLiteralsDescription

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| <<next>>
| -
|===

Description should be descriptive.

If example group or example contains only `execute string`, numbers
and regular expressions, the description is not clear.

=== Examples

[source,ruby]
----
# bad
describe `time` do
# ...
end

# bad
context /when foo/ do
# ...
end

# bad
it 10000 do
# ...
end

# good
describe Foo do
# ...
end

# good
describe '#foo' do
# ...
end

# good
context "when #{foo} is bar" do
# ...
end

# good
it 'does something' do
# ...
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UndescriptiveLiteralsDescription

== RSpec/UnspecifiedException

|===
Expand Down
69 changes: 69 additions & 0 deletions lib/rubocop/cop/rspec/undescriptive_literals_description.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Description should be descriptive.
#
# If example group or example contains only `execute string`, numbers
# and regular expressions, the description is not clear.
#
# @example
# # bad
# describe `time` do
# # ...
# end
#
# # bad
# context /when foo/ do
# # ...
# end
#
# # bad
# it 10000 do
# # ...
# end
#
# # good
# describe Foo do
# # ...
# end
#
# # good
# describe '#foo' do
# # ...
# end
#
# # good
# context "when #{foo} is bar" do
# # ...
# end
#
# # good
# it 'does something' do
# # ...
# end
#
class UndescriptiveLiteralsDescription < Base
MSG = 'Description should be descriptive.'

# @!method example_groups_or_example?(node)
def_node_matcher :example_groups_or_example?, <<~PATTERN
(block (send #rspec? {#ExampleGroups.all #Examples.all} $_) ...)
PATTERN

def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
example_groups_or_example?(node) do |arg|
add_offense(arg) if offense?(arg)
end
end

private

def offense?(node)
%i[xstr int regexp].include?(node.type)
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rspec_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
require_relative 'rspec/stubbed_mock'
require_relative 'rspec/subject_declaration'
require_relative 'rspec/subject_stub'
require_relative 'rspec/undescriptive_literals_description'
require_relative 'rspec/unspecified_exception'
require_relative 'rspec/variable_definition'
require_relative 'rspec/variable_name'
Expand Down
133 changes: 133 additions & 0 deletions spec/rubocop/cop/rspec/undescriptive_literals_description_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::UndescriptiveLiteralsDescription, :config do
it 'registers an offense when using `describe` with only execute string' do
expect_offense(<<~RUBY)
describe `time` do
^^^^^^ Description should be descriptive.
end
RUBY
end

it 'registers an offense when using `context` with only execute string' do
expect_offense(<<~RUBY)
context `time` do
^^^^^^ Description should be descriptive.
end
RUBY
end

it 'registers an offense when using `it` with only execute string' do
expect_offense(<<~RUBY)
it `time` do
^^^^^^ Description should be descriptive.
end
RUBY
end

it 'registers an offense when using `describe` with only regex' do
expect_offense(<<~RUBY)
describe /time/ do
^^^^^^ Description should be descriptive.
end
RUBY
end

it 'registers an offense when using `describe` with only Integer' do
expect_offense(<<~RUBY)
describe 10000 do
^^^^^ Description should be descriptive.
end
RUBY
end

it 'does not register an offense when using `describe` with method call' do
expect_no_offenses(<<~RUBY)
describe foo.to_s do
end
RUBY
end

it 'does not register an offense when using `describe` with local variable' do
expect_no_offenses(<<~RUBY)
types.each do |type|
describe type do
end
end
RUBY
end

it 'does not register an offense when using `describe` with ' \
'instance variable' do
expect_no_offenses(<<~RUBY)
describe @foo do
end
RUBY
end

it 'does not register an offense when using `describe` with ' \
'grobal variable' do
expect_no_offenses(<<~RUBY)
describe $foo do
end
RUBY
end

it 'does not register an offense when using `describe` with a string' do
expect_no_offenses(<<~RUBY)
describe '#foo' do
end
RUBY
end

it 'does not register an offense when using `describe` with a class' do
expect_no_offenses(<<~RUBY)
describe Foo do
end
RUBY
end

it 'does not register an offense when using `context` with a string' do
expect_no_offenses(<<~RUBY)
context 'when foo is bar' do
end
RUBY
end

it 'does not register an offense when using `it` with a string' do
expect_no_offenses(<<~RUBY)
it 'does something' do
end
RUBY
end

it 'does not register an offense when using `describe` with an ' \
'interpolation string' do
expect_no_offenses(<<~RUBY)
describe "foo \#{bar}" do
end
RUBY
end

it 'does not register an offense when using `describe` with a ' \
'heredoc string' do
expect_no_offenses(<<~RUBY)
describe <<~DESC do
foo
DESC
end
RUBY
end

it 'does not register an offense when using `describe` with a ' \
'string concatenation' do
expect_no_offenses(<<~RUBY)
describe 'foo' + `time` do
context 'when ' + 1.to_s do
it 'returns ' + /something/.to_s do
end
end
end
RUBY
end
end