Skip to content

Commit

Permalink
Add an excessive_create_list cop
Browse files Browse the repository at this point in the history
Cop used to signal when we create a lot of
factory objects with FactoryBot (configurable
with the MaxAmount option)
  • Loading branch information
ddieulivol committed Nov 9, 2023
1 parent fe95441 commit 3eedcf3
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ RSpec/ExampleLength:
- heredoc
Max: 11

RSpec/FactoryBot/ExcessiveCreateList:
Enabled: true

RSpec/FilePath:
Enabled: false

Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Master (Unreleased)

- Add new `RSpec/FactoryBot/ExcessiveCreateList` cop. ([@ddieulivol])

## 2.25.0 (2023-10-27)

- Add support single quoted string and percent string and heredoc for `RSpec/Rails/HttpStatus`. ([@ydah])
Expand Down
7 changes: 7 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,13 @@ RSpec/FactoryBot/CreateList:
VersionChanged: '2.23'
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList

RSpec/FactoryBot/ExcessiveCreateList:
Description: Check for create_list FactoryBot declarations higher than configured
MaxAmount.
Enabled: pending
VersionAdded: '2.26'
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/ExcessiveCreateList

RSpec/FactoryBot/FactoryClassName:
Description: Use string value when setting the class attribute explicitly.
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 @@ -122,6 +122,7 @@
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/attributedefinedstatically[RSpec/FactoryBot/AttributeDefinedStatically]
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/consistentparenthesesstyle[RSpec/FactoryBot/ConsistentParenthesesStyle]
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/createlist[RSpec/FactoryBot/CreateList]
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/excessivecreatelist[RSpec/FactoryBot/ExcessiveCreateList]
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/factoryclassname[RSpec/FactoryBot/FactoryClassName]
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/factorynamestyle[RSpec/FactoryBot/FactoryNameStyle]
* xref:cops_rspec_factorybot.adoc#rspecfactorybot/syntaxmethods[RSpec/FactoryBot/SyntaxMethods]
Expand Down
47 changes: 47 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec_factorybot.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,53 @@ create_list :user, 3

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

== RSpec/FactoryBot/ExcessiveCreateList

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

| Pending
| Yes
| No
| 2.26
| -
|===

Check for create_list FactoryBot declarations
higher than configured MaxAmount.

=== Examples

==== MaxAmount: 20

[source,ruby]
----
# We do not allow more than 20 items to be created
# bad
create_list(:merge_request, 1000, state: :opened)
# good
create_list(:merge_request, 15, state: :opened)
----

==== MaxAmount: 10 (default)

[source,ruby]
----
# We do not allow more than 10 items to be created
# bad
create_list(:merge_request, 1000, state: :opened)
# good
create_list(:merge_request, 10, state: :opened)
----

=== References

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

== RSpec/FactoryBot/FactoryClassName

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

module Rubocop
module Cop
module RSpec
module FactoryBot
# Check for create_list FactoryBot declarations
# higher than configured MaxAmount.
#
# @example MaxAmount: 20
# # We do not allow more than 20 items to be created
#
# # bad
# create_list(:merge_request, 1000, state: :opened)
#
# # good
# create_list(:merge_request, 15, state: :opened)
#
# @example MaxAmount: 10 (default)
# # We do not allow more than 10 items to be created
#
# # bad
# create_list(:merge_request, 1000, state: :opened)
#
# # good
# create_list(:merge_request, 10, state: :opened)
#
class ExcessiveCreateList < RuboCop::Cop::RSpec::Base
MESSAGE =
'Avoid using `create_list` with more than %<max_amount>s items.'

# @!method create_list?(node)
def_node_matcher :create_list?, <<~PATTERN
(send nil? :create_list (sym ...) $(int _) ...)
PATTERN

RESTRICT_ON_SEND = %i[create_list].freeze

def on_send(node)
number_node = create_list?(node)
return unless number_node

max_amount = cop_config['MaxAmount']
return if number_node.value <= max_amount

add_offense(number_node, message:
format(MESSAGE, max_amount: max_amount))
end
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 @@ -12,6 +12,7 @@
require_relative 'rspec/factory_bot/attribute_defined_statically'
require_relative 'rspec/factory_bot/consistent_parentheses_style'
require_relative 'rspec/factory_bot/create_list'
require_relative 'rspec/factory_bot/excessive_create_list'
require_relative 'rspec/factory_bot/factory_class_name'
require_relative 'rspec/factory_bot/factory_name_style'
require_relative 'rspec/factory_bot/syntax_methods'
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop/rspec/config_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ConfigFormatter
RSpec/FactoryBot/AttributeDefinedStatically
RSpec/FactoryBot/ConsistentParenthesesStyle
RSpec/FactoryBot/CreateList
RSpec/FactoryBot/ExcessiveCreateList
RSpec/FactoryBot/FactoryClassName
RSpec/FactoryBot/FactoryNameStyle
RSpec/FactoryBot/SyntaxMethods
Expand Down
44 changes: 44 additions & 0 deletions spec/rubocop/cop/rspec/factory_bot/excessive_create_list_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Rubocop::Cop::RSpec::FactoryBot::ExcessiveCreateList do
let(:cop_config) do
{ 'MaxAmount' => max_amount }
end

context 'when MaxAmount is set to 50' do
let(:max_amount) { 50 }

it 'ignores code that does not contain create_list' do
expect_no_offenses(<<~RUBY)
expect(true).to be_truthy
RUBY
end

it 'ignores create_list with non-integer value' do
expect_no_offenses(<<~RUBY)
create_list(:merge_requests, value)
RUBY
end

it 'ignores create_list with less than 50 items' do
expect_no_offenses(<<~RUBY)
create_list(:merge_requests, 30)
RUBY
end

it 'ignores create_list for 50 items' do
expect_no_offenses(<<~RUBY)
create_list(:merge_requests, 50)
RUBY
end

it 'registers an offense for create_list for more than 50 items' do
expect_offense(<<~RUBY)
create_list(:merge_requests, 51)
^^ Avoid using `create_list` with more than 50 items.
RUBY
end
end
end

0 comments on commit 3eedcf3

Please sign in to comment.