Class: Aidp::Harness::TestRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/harness/test_runner.rb

Overview

Executes test and linter commands configured in aidp.yml Returns results with exit status and output Applies intelligent output filtering to reduce token consumption

Supports both legacy category-specific commands (test_commands, lint_commands, etc.) and the new generic commands array with run_after phases.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_dir, config) ⇒ TestRunner

Returns a new instance of TestRunner.



18
19
20
21
22
23
24
25
# File 'lib/aidp/harness/test_runner.rb', line 18

def initialize(project_dir, config)
  @project_dir = project_dir
  @config = config
  @iteration_count = 0
  @filter_stats = {total_input_bytes: 0, total_output_bytes: 0}
  @previous_iteration_had_test_failures = false
  @rspec_optimizer = RSpecCommandOptimizer.new(project_dir)
end

Instance Attribute Details

#filter_statsObject (readonly)

Get filtering statistics



133
134
135
# File 'lib/aidp/harness/test_runner.rb', line 133

def filter_stats
  @filter_stats
end

#iteration_countObject (readonly)

Get current iteration count



130
131
132
# File 'lib/aidp/harness/test_runner.rb', line 130

def iteration_count
  @iteration_count
end

#previous_iteration_had_test_failuresObject (readonly)

Track if previous iteration had test failures (for --only-failures optimization)



139
140
141
# File 'lib/aidp/harness/test_runner.rb', line 139

def previous_iteration_had_test_failures
  @previous_iteration_had_test_failures
end

#rspec_optimizerObject (readonly)

Get RSpec command optimizer (for inspection/testing)



136
137
138
# File 'lib/aidp/harness/test_runner.rb', line 136

def rspec_optimizer
  @rspec_optimizer
end

Instance Method Details

#commands_by_phaseHash

Get all commands organized by phase

Returns:

  • (Hash)

    Commands grouped by run_after phase



77
78
79
80
81
82
83
# File 'lib/aidp/harness/test_runner.rb', line 77

def commands_by_phase
  {
    each_unit: @config.commands_for_phase(:each_unit),
    full_loop: @config.commands_for_phase(:full_loop),
    on_completion: @config.commands_for_phase(:on_completion)
  }
end

#planned_commandsObject

Preview the commands that will run for each category so callers can log intent Returns a hash of category => array of normalized command entries



119
120
121
122
123
124
125
126
127
# File 'lib/aidp/harness/test_runner.rb', line 119

def planned_commands
  {
    tests: resolved_commands(:test),
    lints: resolved_commands(:lint),
    formatters: resolved_commands(:formatter),
    builds: resolved_commands(:build),
    docs: resolved_commands(:documentation)
  }
end

#reset_iteration_countObject

Reset iteration counter (useful for testing)



142
143
144
145
146
# File 'lib/aidp/harness/test_runner.rb', line 142

def reset_iteration_count
  @iteration_count = 0
  @previous_iteration_had_test_failures = false
  @rspec_optimizer.reset_caches!
end

#run_buildsObject

Run all configured build commands Returns: { success: boolean, output: string, failures: array, required_failures: array }



107
108
109
# File 'lib/aidp/harness/test_runner.rb', line 107

def run_builds
  run_command_category(:build, "Build")
end

#run_commands_for_phase(phase) ⇒ Hash

Run all commands configured for a specific execution phase

Parameters:

  • phase (Symbol)

    :each_unit, :full_loop, or :on_completion

Returns:

  • (Hash)

    Aggregated results with success status and outputs by command



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/aidp/harness/test_runner.rb', line 30

def run_commands_for_phase(phase)
  @iteration_count += 1
  commands = @config.commands_for_phase(phase)

  Aidp.log_debug("test_runner", "running_commands_for_phase",
    phase: phase,
    command_count: commands.length,
    iteration: @iteration_count)

  return empty_results if commands.empty?

  results_by_command = {}
  all_failures = []
  required_failures = []

  commands.each do |cmd_config|
    result = execute_command(cmd_config[:command], cmd_config[:category].to_s)
    result[:name] = cmd_config[:name]
    result[:category] = cmd_config[:category]
    result[:required] = cmd_config[:required]

    results_by_command[cmd_config[:name]] = result

    unless result[:success]
      all_failures << result
      required_failures << result if cmd_config[:required]
    end
  end

  success = required_failures.empty?
  output = if all_failures.empty?
    "All #{commands.length} commands passed"
  else
    format_phase_failures(all_failures, phase)
  end

  {
    success: success,
    output: output,
    failures: all_failures,
    required_failures: required_failures,
    results_by_command: results_by_command
  }
end

#run_documentationObject

Run all configured documentation commands Returns: { success: boolean, output: string, failures: array, required_failures: array }



113
114
115
# File 'lib/aidp/harness/test_runner.rb', line 113

def run_documentation
  run_command_category(:documentation, "Documentation")
end

#run_formattersObject

Run all configured formatters Returns: { success: boolean, output: string, failures: array, required_failures: array }



101
102
103
# File 'lib/aidp/harness/test_runner.rb', line 101

def run_formatters
  run_command_category(:formatter, "Formatters")
end

#run_lintersObject

Run all configured linters Returns: { success: boolean, output: string, failures: array, required_failures: array }



94
95
96
97
# File 'lib/aidp/harness/test_runner.rb', line 94

def run_linters
  @iteration_count += 1
  run_command_category(:lint, "Linters")
end

#run_testsObject

Run all configured tests Returns: { success: boolean, output: string, failures: array, required_failures: array }



87
88
89
90
# File 'lib/aidp/harness/test_runner.rb', line 87

def run_tests
  @iteration_count += 1
  run_command_category(:test, "Tests")
end