Skip to content

Commit

Permalink
Add new RSpec/MultipleTestTargetsPerSpecFile cop
Browse files Browse the repository at this point in the history
  • Loading branch information
ydah committed Aug 16, 2023
1 parent ff30ce1 commit 89c8a4c
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Expand Up @@ -153,6 +153,8 @@ RSpec/IndexedLet:
Enabled: true
RSpec/MatchArray:
Enabled: true
RSpec/MultipleTestTargetsPerSpecFile:
Enabled: true
RSpec/NoExpectationExample:
Enabled: true
RSpec/PendingWithoutReason:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
## Master (Unreleased)

- Fix an infinite loop error when `RSpec/ExcessiveDocstringSpacing` finds a description with non-ASCII leading/trailing whitespace. ([@bcgraham])
- Add new `RSpec/MultipleTestTargetsPerSpecFile` cop. ([@ydah])

## 2.23.2 (2023-08-09)

Expand Down
6 changes: 6 additions & 0 deletions config/default.yml
Expand Up @@ -649,6 +649,12 @@ RSpec/MultipleSubjects:
VersionAdded: '1.16'
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects

RSpec/MultipleTestTargetsPerSpecFile:
Description: Checks that spec files only include one test target object.
Enabled: pending
VersionAdded: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleTestTargetsPerSpecFile

RSpec/NamedSubject:
Description: Checks for explicitly referenced test subjects.
Enabled: true
Expand Down
51 changes: 51 additions & 0 deletions lib/rubocop/cop/rspec/multiple_test_targets_per_spec_file.rb
@@ -0,0 +1,51 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Checks that spec files only include one test target object.
#
# @example
# # bad
# RSpec.describe User do
# # ...
# decribe User::Admin do

Check failure on line 12 in lib/rubocop/cop/rspec/multiple_test_targets_per_spec_file.rb

View workflow job for this annotation

GitHub Actions / CodeSpell

decribe ==> describe
# # ...
# end
# end
#
# # bad
# RSpec.describe User do
# # ...
# end
# RSpec.describe Admin do
# # ...
# end
#
# # good
# RSpec.describe User do
# # ...
# end
#
class MultipleTestTargetsPerSpecFile < Base
MSG = 'Spec files should only include one test target object.'

# @!method describe_classes(node)
def_node_search :describe_classes, <<~PATTERN
(block $(send #rspec? #ExampleGroups.all (const ...) ...) ...)
PATTERN

def on_investigation_end
return unless processed_source.ast

describes = describe_classes(processed_source.ast)
return if describes.count <= 1

describes.each do |node|
add_offense(node)
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rspec_cops.rb
Expand Up @@ -91,6 +91,7 @@
require_relative 'rspec/multiple_expectations'
require_relative 'rspec/multiple_memoized_helpers'
require_relative 'rspec/multiple_subjects'
require_relative 'rspec/multiple_test_targets_per_spec_file'
require_relative 'rspec/named_subject'
require_relative 'rspec/nested_groups'
require_relative 'rspec/no_expectation_example'
Expand Down
45 changes: 45 additions & 0 deletions spec/rubocop/cop/rspec/multiple_test_targets_per_spec_file_spec.rb
@@ -0,0 +1,45 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::MultipleTestTargetsPerSpecFile, :config do
it 'registers an offense when include a class and a nested class describe' do
expect_offense(<<~RUBY)
RSpec.describe User do
^^^^^^^^^^^^^^^^^^^ Spec files should only include one test target object.
# ...
describe User::Admin do
^^^^^^^^^^^^^^^^^^^^ Spec files should only include one test target object.
# ...
end
describe User::Moderator do
^^^^^^^^^^^^^^^^^^^^^^^^ Spec files should only include one test target object.
# ...
end
end
RUBY
end

it 'registers an offense when include multiple classes' do
expect_offense(<<~RUBY)
RSpec.describe User do
^^^^^^^^^^^^^^^^^^^ Spec files should only include one test target object.
# ...
end
RSpec.describe Admin do
^^^^^^^^^^^^^^^^^^^^ Spec files should only include one test target object.
# ...
end
RUBY
end

it 'does not register an offense when include only class' do
expect_no_offenses(<<~RUBY)
RSpec.describe User do
describe '#method' do
# ...
end
end
RUBY
end
end

0 comments on commit 89c8a4c

Please sign in to comment.