Development
This page describes considerations when developing RSpec-specific cops. It is intended to be a complement to the general RuboCop development documentation.
Create a new cop
Clone the repository and run bundle install if not done yet.
The following rake task can only be run inside the rubocop project directory itself.
|
Use the bundled rake task new_cop
to generate a cop template:
$ bundle exec rake 'new_cop[RSpec/CopName]'
[create] lib/rubocop/cop/rspec/cop_name.rb
[create] spec/rubocop/cop/rspec/cop_name_spec.rb
[modify] lib/rubocop/cop/rspec_cops.rb - `require_relative 'rspec/cop_name'` was injected.
[modify] A configuration for the cop is added into config/default.yml.
Do 4 steps:
1. Modify the description of RSpec/CopName in config/default.yml
2. Implement your new cop in the generated file!
3. Add an entry about new cop to CHANGELOG.md
4. Commit your new cop with a message such as
e.g. "Add new `#{badge}` cop"
Choose a Name
Use the following rules to give the new cop a name:
-
Pick a department. See the list of existing departments
-
The name is self-explanatory
-
The name explains the offense the cop detects, e.g.
ExtraSpacing
-
The name starts with a noun instead of a verb, e.g.
ArrayAlignment
instead ofAlignArray
-
The name is easy to understand, e.g.
IndentationStyle
instead of justTab
-
The name is specific, e.g.
DuplicateHashKey
instead of justDuplicateKey
-
The name is neutral when possible and accommodates multiple styles when feasible, e.g.
EmptyLineBeforeBegin
. -
The name uses commonly-used terms, e.g.
RedundantPercentI
instead ofRedundantPercentSymbolArray
-
The name uses correct terms, e.g. arguments in a method call, and parameters in a method signature
-
Lines with no symbols are called "empty", not "blank", e.g.
LeadingEmptyLines
instead ofLeadingBlankLines
-
Prefer "redundant" to "unneeded", e.g.
RedundantSelf
instead ofUnneededSelf
See the "renamed" section of config/obsoletion.yml
for good and bad examples (old name is on the left, new name on the right).
Base class
The RuboCop::Cop::RSpec::Base
class includes convenient node pattern DSL matchers that will automatically account for any custom RSpec DSL configuration.
For example, if the project defines let_it_be
as a Helper
, then all cops will find let_it_be
when using the let?
matcher.
Writing specs
When working on RSpec-specific cops, ensure that the default language config is loaded for all RSpec specs. For example:
require 'rubocop/rspec/shared_contexts/default_rspec_language_config_context'
RSpec.config do |config|
# Set metadata on all cop specs
config.define_derived_metadata(file_path: %r{/spec/rubocop/cop/}) do |meta|
meta[:type] = :cop_spec
end
# Include RuboCop's config shared context for all cop specs
config.define_derived_metadata(type: :cop_spec) do |meta|
meta[:config] = true
end
config.include_context 'with default RSpec/Language config', :config
end