lib/rspec_tracer/reporter.rb
# frozen_string_literal: true
module RSpecTracer
class Reporter
attr_reader :all_examples, :interrupted_examples, :duplicate_examples,
:possibly_flaky_examples, :flaky_examples, :pending_examples,
:skipped_examples, :failed_examples, :all_files, :modified_files,
:deleted_files, :dependency, :examples_coverage
attr_accessor :reverse_dependency, :last_run
def initialize
initialize_examples
initialize_files
initialize_dependency
initialize_coverage
end
def register_example(example)
@all_examples[example[:example_id]] = example
@duplicate_examples[example[:example_id]] << example
end
def deregister_duplicate_examples
@duplicate_examples.select! { |_, examples| examples.count > 1 }
return if @duplicate_examples.empty?
@all_examples.reject! { |example_id, _| @duplicate_examples.key?(example_id) }
end
def on_example_skipped(example_id)
@skipped_examples << example_id
end
def on_example_passed(example_id, result)
return if @duplicate_examples.key?(example_id)
@passed_examples << example_id
@all_examples[example_id][:execution_result] = formatted_execution_result(result)
end
def on_example_failed(example_id, result)
return if @duplicate_examples.key?(example_id)
@failed_examples << example_id
@all_examples[example_id][:execution_result] = formatted_execution_result(result)
end
def on_example_pending(example_id, result)
return if @duplicate_examples.key?(example_id)
@pending_examples << example_id
@all_examples[example_id][:execution_result] = formatted_execution_result(result)
end
def register_interrupted_examples
@all_examples.each_pair do |example_id, example|
next if example.key?(:execution_result)
@interrupted_examples << example_id
end
return if @interrupted_examples.empty?
RSpecTracer.logger.info "RSpec tracer is not processing #{@interrupted_examples.count} interrupted examples"
end
def register_deleted_examples(seen_examples)
@deleted_examples = seen_examples.keys.to_set - (@skipped_examples | @all_examples.keys)
@deleted_examples -= @interrupted_examples
@deleted_examples.select! do |example_id|
example = seen_examples[example_id]
file_changed?(example[:file_name]) || file_changed?(example[:rerun_file_name])
end
end
def register_possibly_flaky_example(example_id)
@possibly_flaky_examples << example_id
end
def register_flaky_example(example_id)
@flaky_examples << example_id
end
def register_failed_example(example_id)
@failed_examples << example_id
end
def register_pending_example(example_id)
@pending_examples << example_id
end
def duplicate_example?(example_id)
@duplicate_examples.key?(example_id)
end
def example_interrupted?(example_id)
@interrupted_examples.include?(example_id)
end
def example_passed?(example_id)
@passed_examples.include?(example_id)
end
def example_skipped?(example_id)
@skipped_examples.include?(example_id)
end
def example_failed?(example_id)
@failed_examples.include?(example_id)
end
def example_pending?(example_id)
@pending_examples.include?(example_id)
end
def example_deleted?(example_id)
@deleted_examples.include?(example_id)
end
def register_source_file(source_file)
@all_files[source_file[:file_name]] = source_file
end
def on_file_deleted(file_name)
@deleted_files << file_name
end
def on_file_modified(file_name)
@modified_files << file_name
end
def file_deleted?(file_name)
@deleted_files.include?(file_name)
end
def file_modified?(file_name)
@modified_files.include?(file_name)
end
def file_changed?(file_name)
file_deleted?(file_name) || file_modified?(file_name)
end
def register_dependency(example_id, file_name)
@dependency[example_id] << file_name
end
def register_examples_coverage(examples_coverage)
@examples_coverage = examples_coverage
end
private
def initialize_examples
@all_examples = {}
@duplicate_examples = Hash.new { |examples, example_id| examples[example_id] = [] }
@interrupted_examples = Set.new
@passed_examples = Set.new
@possibly_flaky_examples = Set.new
@flaky_examples = Set.new
@failed_examples = Set.new
@skipped_examples = Set.new
@pending_examples = Set.new
@deleted_examples = Set.new
end
def initialize_files
@all_files = {}
@modified_files = Set.new
@deleted_files = Set.new
end
def initialize_dependency
@dependency = Hash.new { |hash, key| hash[key] = Set.new }
@reverse_dependency = Hash.new do |examples, file_name|
examples[file_name] = {
example_count: 0,
examples: Hash.new(0)
}
end
end
def initialize_coverage
@examples_coverage = Hash.new do |examples, example_id|
examples[example_id] = Hash.new do |files, file_name|
files[file_name] = {}
end
end
end
def formatted_execution_result(result)
{
started_at: result.started_at.utc,
finished_at: result.finished_at.utc,
run_time: result.run_time,
status: result.status.to_s
}
end
end
end