Class: Ace::TestRunner::Organisms::TestOrchestrator
- Inherits:
-
Object
- Object
- Ace::TestRunner::Organisms::TestOrchestrator
- Defined in:
- lib/ace/test_runner/organisms/test_orchestrator.rb
Overview
Main orchestrator that coordinates the entire test execution flow
Instance Attribute Summary collapse
-
#configuration ⇒ Object
readonly
Returns the value of attribute configuration.
-
#result ⇒ Object
readonly
Returns the value of attribute result.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ TestOrchestrator
constructor
A new instance of TestOrchestrator.
- #run ⇒ Object
- #run_with_package_context ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ TestOrchestrator
Returns a new instance of TestOrchestrator.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/ace/test_runner/organisms/test_orchestrator.rb', line 16 def initialize( = {}) @package_dir = [:package_dir] @original_dir = Dir.pwd @options = # Fail fast: validate package_dir exists before proceeding if @package_dir && !Dir.exist?(@package_dir) raise Error, "Package directory not found: #{@package_dir}" end # Track if user explicitly specified --report-dir to avoid auto-detection override @report_dir_override = [:report_dir] ? :user_specified : nil # Component initialization strategy: # - Package mode: defer setup to run() when we're in the correct directory # - Non-package mode: set up immediately for backward compatibility # (callers may access @configuration after initialize) if @package_dir @configuration = nil @components_initialized = false else setup_components @components_initialized = true end end |
Instance Attribute Details
#configuration ⇒ Object (readonly)
Returns the value of attribute configuration.
14 15 16 |
# File 'lib/ace/test_runner/organisms/test_orchestrator.rb', line 14 def configuration @configuration end |
#result ⇒ Object (readonly)
Returns the value of attribute result.
14 15 16 |
# File 'lib/ace/test_runner/organisms/test_orchestrator.rb', line 14 def result @result end |
Instance Method Details
#run ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/ace/test_runner/organisms/test_orchestrator.rb', line 42 def run # Change to package directory if specified - this is done in run to ensure # the ensure block always restores the directory, even on initialization errors Dir.chdir(@package_dir) if @package_dir # Initialize components if not already done (package mode) setup_components unless @components_initialized run_with_package_context ensure # Restore original directory if we changed it Dir.chdir(@original_dir) if @package_dir && Dir.pwd != @original_dir end |
#run_with_package_context ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/ace/test_runner/organisms/test_orchestrator.rb', line 56 def run_with_package_context validate_configuration! start_time = Time.now # Print package context if running in different directory if @package_dir puts "Running tests in #{File.basename(@package_dir)}..." end # Check if sequential target execution should be used if should_execute_sequentially? # Use default "fast" target if no target specified in by-target mode @configuration.target ||= "fast" return run_sequential_targets(start_time) end # Find test files test_files = find_test_files if test_files.empty? return handle_no_tests end resolve_and_set_report_dir_context(test_files) # Count total available test files (before filtering) total_available = count_total_test_files # Notify start with both counts if @formatter.respond_to?(:on_start_with_totals) @formatter.on_start_with_totals(test_files.size, total_available) else @formatter.on_start(test_files.size) end # Execute tests execution_result = execute_tests(test_files) # Check if execution failed with LoadError (stdout is empty means tests didn't run) @parsed_result = if !execution_result[:success] && execution_result[:stdout].to_s.empty? && execution_result[:stderr] && !execution_result[:stderr].empty? # Handle load errors or other failures that prevented test execution { summary: { runs: 0, assertions: 0, failures: 0, errors: test_files.size, # Count all test files as errors skips: 0, passed: 0 }, failures: [], errors: [{ message: execution_result[:stderr].strip, type: "LoadError", files: test_files }], deprecations: [], duration: execution_result[:duration] } elsif execution_result[:commands] && execution_result[:commands].is_a?(Array) # Each file was executed separately, parse and sum them all aggregate_individual_results(execution_result[:stdout]) else # Single command execution (by-target) @result_parser.parse_output(execution_result[:stdout]) end # Build result object @result = build_result(@parsed_result, execution_result, start_time) # Analyze failures and errors if @result.has_failures? # Collect both failures and errors for analysis all_failures = @parsed_result[:failures] || [] # Convert errors to failure format if present if @parsed_result[:errors] && @parsed_result[:errors].any? error_failures = @parsed_result[:errors].map do |error| { type: :error, test_name: error[:type] || "LoadError", message: error[:message] || "Unknown error", location: nil, full_content: error[:message] || "Unknown error", files: error[:files] } end all_failures += error_failures end analyzed_failures = @failure_analyzer.analyze_all( all_failures, stderr: @result.stderr ) @result.failures_detail = analyzed_failures end # Generate and save report report = @report_generator.generate(@result, test_files) # Save reports if configured if @configuration.save_reports report_path = save_reports(report) # Pass report path to formatter before outputting @formatter.report_path = report_path if @formatter.respond_to?(:report_path=) end # Output to stdout @formatter.on_finish(@result) # Display profile results if requested if @configuration.profile && @parsed_result[:test_times] && !@parsed_result[:test_times].empty? display_profile(@parsed_result[:test_times], @configuration.profile) end # Return exit code @result.success? ? 0 : 1 end |