ace-test-runner 0.19.1 → 0.25.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,7 +97,7 @@ module Ace
97
97
  exit_status = thread.value.exitstatus
98
98
 
99
99
  collect_remaining_output(process_info)
100
- results = build_results(process_info, elapsed)
100
+ results = build_results(process_info, elapsed, exit_status)
101
101
  close_streams(process_info)
102
102
 
103
103
  # Final callback
@@ -182,8 +182,8 @@ module Ace
182
182
  def build_command(package, options)
183
183
  cmd_parts = ["ace-test"]
184
184
 
185
- # Always run in single batch for suite execution
186
- # This avoids nested group headers and improves performance
185
+ # Suite package execution intentionally bypasses grouped mode so each
186
+ # package runs its full target scope as one batch under suite orchestration.
187
187
  cmd_parts << "--run-in-single-batch"
188
188
 
189
189
  # Add format (use progress if compact is specified since ace-test doesn't have compact format)
@@ -201,6 +201,9 @@ module Ace
201
201
  cmd_parts << "--report-dir" << pkg_report_dir
202
202
  end
203
203
 
204
+ target = options["target"]
205
+ cmd_parts << target if target && !target.to_s.empty?
206
+
204
207
  cmd_parts
205
208
  end
206
209
 
@@ -275,11 +278,12 @@ module Ace
275
278
  end
276
279
  end
277
280
 
278
- def build_results(process_info, elapsed)
281
+ def build_results(process_info, elapsed, exit_status)
279
282
  return timeout_results(process_info, elapsed) if process_info[:timeout_triggered]
280
283
  return interrupted_results(elapsed) if process_info[:terminated_by] == :interrupt
281
- results = load_summary_results(process_info, elapsed)
282
- return results if results
284
+ fresh_summary = load_summary_results(process_info, elapsed)
285
+ return fresh_summary if exit_status == 0 && fresh_summary
286
+ return failed_process_results(process_info, elapsed, exit_status, fresh_summary) if exit_status != 0
283
287
 
284
288
  parse_results(process_info[:output])
285
289
  end
@@ -308,6 +312,26 @@ module Ace
308
312
  }
309
313
  end
310
314
 
315
+ def failed_process_results(process_info, elapsed, exit_status, fresh_summary)
316
+ return fresh_summary if fresh_summary && fresh_summary[:success] == false
317
+
318
+ parsed = parse_results([process_info[:output], process_info[:stderr_output]].join("\n"))
319
+ parsed[:duration] ||= elapsed
320
+ parsed[:success] = false
321
+ parsed[:error] ||= failure_message_for(process_info, exit_status)
322
+ parsed[:errors] = 1 if parsed[:failures].to_i == 0 && parsed[:errors].to_i == 0
323
+ parsed
324
+ end
325
+
326
+ def failure_message_for(process_info, exit_status)
327
+ stderr = process_info[:stderr_output].to_s.strip
328
+ stdout = process_info[:output].to_s.strip
329
+ message = stderr.empty? ? stdout : stderr
330
+ return message unless message.empty?
331
+
332
+ "ace-test exited with status #{exit_status}"
333
+ end
334
+
311
335
  def load_summary_results(process_info, elapsed)
312
336
  package = process_info[:package]
313
337
  reports_dir = Atoms::ReportPathResolver.report_directory(
@@ -317,6 +341,7 @@ module Ace
317
341
  )
318
342
  summary_file = reports_dir ? File.join(reports_dir, "summary.json") : nil
319
343
  return nil unless summary_file && File.exist?(summary_file)
344
+ return nil unless summary_fresh_for_run?(summary_file, process_info[:start_time])
320
345
 
321
346
  json_data = JSON.parse(File.read(summary_file))
322
347
  results = {
@@ -324,6 +349,7 @@ module Ace
324
349
  assertions: json_data["assertions"] || 0,
325
350
  failures: json_data["failed"] || 0,
326
351
  errors: json_data["errors"] || 0,
352
+ skipped: json_data["skipped"] || 0,
327
353
  duration: json_data["duration"] || elapsed,
328
354
  success: json_data["success"] || false
329
355
  }
@@ -341,6 +367,12 @@ module Ace
341
367
  nil
342
368
  end
343
369
 
370
+ def summary_fresh_for_run?(summary_file, start_time)
371
+ File.mtime(summary_file) >= (start_time - 0.001)
372
+ rescue StandardError
373
+ false
374
+ end
375
+
344
376
  def parse_progress(process_info, chunk)
345
377
  # Count dots, F, E, S in the output for progress
346
378
  dots = chunk.scan(/[.FES]/).join
@@ -47,6 +47,9 @@ module Ace
47
47
 
48
48
  def collect_results
49
49
  @packages.map do |package|
50
+ runtime = runtime_result(package)
51
+ next runtime if runtime_result_overrides_summary?(package, runtime)
52
+
50
53
  reports_dir = Atoms::ReportPathResolver.report_directory(
51
54
  package["path"],
52
55
  report_root: @report_root,
@@ -91,7 +94,7 @@ module Ace
91
94
  }
92
95
  end
93
96
  else
94
- runtime_result(package) || {
97
+ runtime || {
95
98
  package: package["name"],
96
99
  path: package["path"],
97
100
  report_root: @report_root,
@@ -106,6 +109,13 @@ module Ace
106
109
  end
107
110
  end
108
111
 
112
+ def runtime_result_overrides_summary?(package, runtime)
113
+ return false unless runtime
114
+
115
+ status = @runtime_results[package["name"]] || {}
116
+ status[:timed_out] || status[:interrupted] || runtime[:success] == false
117
+ end
118
+
109
119
  def collect_failed_packages(results)
110
120
  results.select { |r| !r[:success] }.map do |result|
111
121
  {
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module TestRunner
5
- VERSION = '0.19.1'
5
+ VERSION = '0.25.5'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-test-runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.1
4
+ version: 0.25.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-03-29 00:00:00.000000000 Z
10
+ date: 2026-04-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-support-cli
@@ -189,9 +189,9 @@ files:
189
189
  - lib/ace/test_runner/formatters/progress_formatter.rb
190
190
  - lib/ace/test_runner/models/test_configuration.rb
191
191
  - lib/ace/test_runner/models/test_failure.rb
192
- - lib/ace/test_runner/models/test_group.rb
193
192
  - lib/ace/test_runner/models/test_report.rb
194
193
  - lib/ace/test_runner/models/test_result.rb
194
+ - lib/ace/test_runner/models/test_target.rb
195
195
  - lib/ace/test_runner/molecules/cli_argument_parser.rb
196
196
  - lib/ace/test_runner/molecules/config_loader.rb
197
197
  - lib/ace/test_runner/molecules/deprecation_fixer.rb
@@ -206,7 +206,7 @@ files:
206
206
  - lib/ace/test_runner/molecules/test_executor.rb
207
207
  - lib/ace/test_runner/organisms/agent_reporter.rb
208
208
  - lib/ace/test_runner/organisms/report_generator.rb
209
- - lib/ace/test_runner/organisms/sequential_group_executor.rb
209
+ - lib/ace/test_runner/organisms/sequential_target_executor.rb
210
210
  - lib/ace/test_runner/organisms/test_orchestrator.rb
211
211
  - lib/ace/test_runner/rake_task.rb
212
212
  - lib/ace/test_runner/suite.rb