Skip to content

Commit

Permalink
Merge pull request #1796 from rubocop/add-xstr-only
Browse files Browse the repository at this point in the history
Add new `RSpec/UndescriptiveLiteralsDescription` cop
  • Loading branch information
pirj authored Apr 1, 2024
2 parents 6add066 + 83edcf9 commit ef302ee
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 0 deletions.
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

0 comments on commit ef302ee

Please sign in to comment.