Class: RuboCop::Cop::RSpecParity::SufficientContexts

Inherits:
Base
  • Object
show all
Includes:
DepartmentConfig, SpecFileFinder
Defined in:
lib/rubocop/cop/rspec_parity/sufficient_contexts.rb

Overview

Ensures that specs have at least as many contexts as the method has branches.

This cop helps ensure thorough test coverage by checking that complex methods with multiple branches (if/elsif/else, case/when, &&, ||, ternary) have corresponding context blocks in their specs to test each branch.

Examples:

# bad - method has 3 branches, spec has only 1 context
# app/services/user_creator.rb
def create_user(params)
  if params[:admin]
    create_admin(params)
  elsif params[:moderator]
    create_moderator(params)
  else
    create_regular_user(params)
  end
end

# spec/services/user_creator_spec.rb
context 'when creating a user' do
  # only one context for 3 branches
end

# good - method has 3 branches, spec has 3 contexts
# spec/services/user_creator_spec.rb
context 'when creating an admin' do
end
context 'when creating a moderator' do
end
context 'when creating a regular user' do
end

Defined Under Namespace

Classes: BranchTally, ParsedSpec

Constant Summary collapse

MSG =
"Method `%<method_name>s` has %<branches>d %<branch_word>s but the spec covers only " \
"%<contexts>d %<scenario_word>s. Add %<missing>d more %<missing_word>s " \
"(one `context` or `it` per branch; compound conditions like `a && b` need a scenario per operand)."
TRACED_SUFFIX =
" (including branches from: %<traced>s)"
APP_DIR_PATTERN =
%r{/app/}
EXCLUDED_METHODS =
%w[initialize].freeze
EXCLUDED_PATTERNS =
[
  /^before_/,
  /^after_/,
  /^around_/,
  /^validate_/,
  /^autosave_/
].freeze
GUARD_TERMINATOR_TYPES =

Node types whose presence as a one-armed ‘if` body makes it a guard clause.

%i[return break next redo retry].freeze

Constants included from DepartmentConfig

DepartmentConfig::SHARED_CONFIG_DEFAULTS

Instance Method Summary collapse

Constructor Details

#initialize(config = nil, options = nil) ⇒ SufficientContexts

Returns a new instance of SufficientContexts.



84
85
86
87
88
89
# File 'lib/rubocop/cop/rspec_parity/sufficient_contexts.rb', line 84

def initialize(config = nil, options = nil)
  super
  @ignore_memoization = cop_config.fetch("IgnoreMemoization", true)
  @trace_single_use_private = cop_config.fetch("TraceSingleUsePrivateMethods", true)
  @call_graphs = {}.compare_by_identity
end

Instance Method Details

#on_def(node) ⇒ Object



91
92
93
# File 'lib/rubocop/cop/rspec_parity/sufficient_contexts.rb', line 91

def on_def(node)
  check_method(node)
end

#on_defs(node) ⇒ Object



95
96
97
# File 'lib/rubocop/cop/rspec_parity/sufficient_contexts.rb', line 95

def on_defs(node)
  check_method(node)
end