Class: RuboCop::Cop::RSpec::EmptyExampleGroup

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/rspec/empty_example_group.rb

Overview

Checks if an example group does not include any tests.

Examples:

usage


# bad
describe Bacon do
  let(:bacon)      { Bacon.new(chunkiness) }
  let(:chunkiness) { false                 }

  context 'extra chunky' do   # flagged by rubocop
    let(:chunkiness) { true }
  end

  it 'is chunky' do
    expect(bacon.chunky?).to be_truthy
  end
end

# good
describe Bacon do
  let(:bacon)      { Bacon.new(chunkiness) }
  let(:chunkiness) { false                 }

  it 'is chunky' do
    expect(bacon.chunky?).to be_truthy
  end
end

# good
describe Bacon do
  pending 'will add tests later'
end

Constant Summary collapse

MSG =
'Empty example group detected.'

Instance Method Summary collapse

Methods inherited from Base

inherited, #on_new_investigation

Methods included from RSpec::Language::NodePattern

#block_pattern, #send_pattern

Instance Method Details

#example_group_body(node) {|RuboCop::AST::Node| ... } ⇒ Object

Match example group blocks and yield their body

Examples:

source that matches

describe 'example group' do
  it { is_expected.to be }
end

Parameters:

  • node (RuboCop::AST::Node)

Yields:

  • (RuboCop::AST::Node)

    example group body


51
52
53
# File 'lib/rubocop/cop/rspec/empty_example_group.rb', line 51

def_node_matcher :example_group_body, <<~PATTERN
  (block #{send_pattern('#ExampleGroups.all')} args $_)
PATTERN

#example_or_group_or_include?(node) ⇒ Array<RuboCop::AST::Node>

Match examples, example groups and includes

Examples:

source that matches

it { is_expected.to fly }
describe('non-empty example groups too') { }
it_behaves_like 'an animal'
it_behaves_like('a cat') { let(:food) { 'milk' } }
it_has_root_access
skip
it 'will be implemented later'

Parameters:

  • node (RuboCop::AST::Node)

Returns:

  • (Array<RuboCop::AST::Node>)

    matching nodes


69
70
71
72
73
74
75
76
# File 'lib/rubocop/cop/rspec/empty_example_group.rb', line 69

def_node_matcher :example_or_group_or_include?, <<~PATTERN
  {
    #{block_pattern(
      '{#Examples.all #ExampleGroups.all #Includes.all}'
    )}
    #{send_pattern('{#Examples.all #Includes.all}')}
  }
PATTERN

#examples?(node) ⇒ Array<RuboCop::AST::Node>

Matches examples defined in scopes where they could run

Examples:

source that matches

it { expect(myself).to be_run }
describe { it { i_run_as_well } }

source that does not match

before { it { whatever here wont run anyway } }

Parameters:

  • node (RuboCop::AST::Node)

Returns:

  • (Array<RuboCop::AST::Node>)

    matching nodes


126
127
128
129
130
131
# File 'lib/rubocop/cop/rspec/empty_example_group.rb', line 126

def_node_matcher :examples?, <<~PATTERN
  {
    #examples_directly_or_in_block?
    (begin <#examples_directly_or_in_block? ...>)
  }
PATTERN

#examples_directly_or_in_block?(node) ⇒ Array<RuboCop::AST::Node>

Match examples or examples inside blocks

Examples:

source that matches

it { expect(drink).to be_cold }
context('when winter') { it { expect(drink).to be_hot } }
(1..5).each { |divisor| it { is_expected.to divide_by(divisor) } }

Parameters:

  • node (RuboCop::AST::Node)

Returns:

  • (Array<RuboCop::AST::Node>)

    matching nodes


107
108
109
110
111
112
# File 'lib/rubocop/cop/rspec/empty_example_group.rb', line 107

def_node_matcher :examples_directly_or_in_block?, <<~PATTERN
  {
    #example_or_group_or_include?
    #examples_inside_block?
  }
PATTERN

#examples_inside_block?(node) ⇒ Array<RuboCop::AST::Node>

Match examples defined inside a block which is not a hook

Examples:

source that matches

%w(r g b).each do |color|
  it { is_expected.to have_color(color) }
end

source that does not match

before do
  it { is_expected.to fall_into_oblivion }
end

Parameters:

  • node (RuboCop::AST::Node)

Returns:

  • (Array<RuboCop::AST::Node>)

    matching nodes


93
94
95
# File 'lib/rubocop/cop/rspec/empty_example_group.rb', line 93

def_node_matcher :examples_inside_block?, <<~PATTERN
  (block !#{send_pattern('#Hooks.all')} _ #examples?)
PATTERN

#on_block(node) ⇒ Object


133
134
135
136
137
138
139
140
# File 'lib/rubocop/cop/rspec/empty_example_group.rb', line 133

def on_block(node)
  return if node.each_ancestor(:def, :defs).any?
  return if node.each_ancestor(:block).any? { |block| example?(block) }

  example_group_body(node) do |body|
    add_offense(node.send_node) if offensive?(body)
  end
end