123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Formatter::JUnitFormatter

Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Instance Chain:
Inherits: RuboCop::Formatter::BaseFormatter
Defined in: lib/rubocop/formatter/junit_formatter.rb

Overview

This formatter formats the report data in JUnit format.

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

BaseFormatter - Inherited

#file_finished

Invoked at the end of inspecting each files.

#file_started

Invoked at the beginning of inspecting each files.

#finished

Invoked after all files are inspected or interrupted by user.

#started

Invoked once before any files are inspected.

Constructor Details

.new(output, options = {}) ⇒ JUnitFormatter

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 24

def initialize(output, options = {})
  super

  @test_case_elements = []
  @config_store = nil

  reset_count
end

Instance Method Details

#add_failure_to(testcase, offenses, cop_name) (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 123

def add_failure_to(testcase, offenses, cop_name)
  # One failure per offense. Zero failures is a passing test case,
  # for most surefire/nUnit parsers.
  offenses.each do |offense|
    testcase.failures << FailureElement.new(
      type: cop_name,
      message: offense.message,
      text: offense.location.to_s
    )
  end
end

#add_testcase_element_to_testsuite_element(file, target_offenses, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 92

def add_testcase_element_to_testsuite_element(file, target_offenses, cop)
  @test_case_elements << TestCaseElement.new(
    classname: classname_attribute_value(file),
    name: cop.cop_name
  ).tap do |test_case_element|
    add_failure_to(test_case_element, target_offenses, cop.cop_name)
  end
end

#classname_attribute_value(file) (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 111

def classname_attribute_value(file)
  @classname_attribute_value_cache ||= Hash.new do |hash, key|
    hash[key] = key.delete_suffix('.rb').gsub("#{PathUtil.pwd}/", '').tr('/', '.')
  end
  @classname_attribute_value_cache[file]
end

#cops_for(file) (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 76

def cops_for(file)
  # `file_started` is not called when this formatter is used directly through the API,
  # in which case all cops are returned for compatibility.
  return Cop::Registry.all if @config_store.nil?

  registry.enabled(@config_store.for_file(file))
end

#file_finished(file, offenses)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 37

def file_finished(file, offenses)
  @inspected_file_count += 1
  @offense_count += offenses.count

  cops_for(file).each do |cop|
    target_offenses = offenses_for_cop(offenses, cop)

    next unless relevant_for_output?(options, target_offenses)

    add_testcase_element_to_testsuite_element(file, target_offenses, cop)
  end
end

#file_started(_file, options)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 33

def file_started(_file, options)
  @config_store = options[:config_store]
end

#finished(_inspected_files)

rubocop:disable-next Layout/LineLength,Metrics/AbcSize,Metrics/MethodLength

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 51

def finished(_inspected_files)
  output.puts %(<?xml version='1.0'?>)
  output.puts %(<testsuites>)
  output.puts %(  <testsuite name='rubocop' tests='#{@inspected_file_count}' failures='#{@offense_count}'>)

  @test_case_elements.each do |test_case_element|
    if test_case_element.failures.empty?
      output.puts %(    <testcase classname='#{xml_escape test_case_element.classname}' name='#{test_case_element.name}'/>)
    else
      output.puts %(    <testcase classname='#{xml_escape test_case_element.classname}' name='#{test_case_element.name}'>)
      test_case_element.failures.each do |failure_element|
        output.puts %(      <failure type='#{failure_element.type}' message='#{xml_escape failure_element.message}'>)
        output.puts %(        #{xml_escape failure_element.text})
        output.puts %(      </failure>)
      end
      output.puts %(    </testcase>)
    end
  end

  output.puts %(  </testsuite>)
  output.puts %(</testsuites>)
end

#offenses_for_cop(all_offenses, cop) (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 88

def offenses_for_cop(all_offenses, cop)
  all_offenses.select { |offense| offense.cop_name == cop.cop_name }
end

#registry (private)

Filtering by badge keeps lazy-loaded cops unloaded; Registry#enabled then loads only the enabled cops, the same set the runner mobilizes.

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 103

def registry
  @registry ||= Cop::Registry.global.filter_by_badge(options) do |badge|
    next false if badge.department == :Test || badge.match_name?(options[:except])

    options[:only].nil? || badge.match_name?(options[:only])
  end
end

#relevant_for_output?(options, target_offenses) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 84

def relevant_for_output?(options, target_offenses)
  !options[:display_only_failed] || target_offenses.any?
end

#reset_count (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 118

def reset_count
  @inspected_file_count = 0
  @offense_count = 0
end

#xml_escape(string) (private)

[ GitHub ]

  
# File 'lib/rubocop/formatter/junit_formatter.rb', line 135

def xml_escape(string)
  string.gsub(Regexp.union(ESCAPE_MAP.keys), ESCAPE_MAP)
end