class Tryouts::TestRunner
def apply_framework_defaults(options)
def apply_framework_defaults(options) framework_defaults = FRAMEWORK_DEFAULTS[options[:framework]] || {} framework_defaults.merge(options) end
def handle_file_error(exception)
def handle_file_error(exception) @status = :error Tryouts.debug "TestRunner#process_file: An error occurred processing #{file}: #{ex.message}" error_message = "Batch execution failed: #{exception.message}" backtrace = exception.respond_to?(:backtrace) ? exception.backtrace : nil @output_manager&.error(error_message, backtrace) end
def initialize(files:, options:, output_manager:)
def initialize(files:, options:, output_manager:) @files = files @options = apply_framework_defaults(options) @output_manager = output_manager @translator = initialize_translator @global_tally = initialize_global_tally end
def initialize_global_tally
def initialize_global_tally { total_tests: 0, total_failed: 0, total_errors: 0, file_count: 0, start_time: Time.now, successful_files: 0, failure_collector: FailureCollector.new, } end
def initialize_translator
def initialize_translator return nil if @options[:framework] == :direct FRAMEWORKS[@options[:framework]].new end
def log_run_info
def log_run_info @output_manager.processing_phase(@files.size) @output_manager.info "Framework: #{@options[:framework]}", 1 @output_manager.info "Context: #{@options[:shared_context] ? 'shared' : 'fresh'}", 1 @files.each_with_index do |file, idx| @output_manager.info "#{idx + 1}/#{@files.size}: #{Console.pretty_path(file)}", 1 end end
def process_file(file)
def process_file(file) file = FileProcessor.new( file: file, options: @options, output_manager: @output_manager, translator: @translator, global_tally: @global_tally, ) file.process rescue StandardError => ex handle_file_error(ex) @global_tally[:total_errors] += 1 1 end
def process_files
def process_files failure_count = 0 @files.each_with_index do |file, _idx| result = process_file(file) failure_count += result unless result.zero? status = result.zero? ? Console.color(:green, 'PASS') : Console.color(:red, 'FAIL') @output_manager.info "#{status} #{Console.pretty_path(file)} (#{result} failures)", 1 end failure_count end
def run
def run log_run_info validate_framework result = process_files show_failure_summary show_grand_total if @global_tally[:file_count] > 1 result end
def show_failure_summary
def show_failure_summary # Show failure summary if any failures exist if @global_tally[:failure_collector].any_failures? @output_manager.batch_summary(@global_tally[:failure_collector]) end end
def show_grand_total
def show_grand_total elapsed_time = Time.now - @global_tally[:start_time] @output_manager.grand_total( @global_tally[:total_tests], @global_tally[:total_failed], @global_tally[:total_errors], @global_tally[:successful_files], @global_tally[:file_count], elapsed_time, ) end
def validate_framework
def validate_framework unless @options[:framework] == :direct || FRAMEWORKS.key?(@options[:framework]) raise ArgumentError, "Unknown framework: #{@options[:framework]}. Available: #{FRAMEWORKS.keys.join(', ')}, direct" end end