Class: Ace::TestRunner::Formatters::ProgressFileFormatter

Inherits:
BaseFormatter
  • Object
show all
Defined in:
lib/ace/test_runner/formatters/progress_file_formatter.rb

Overview

Progress formatter that shows one dot per test file (faster execution)

Instance Attribute Summary

Attributes inherited from BaseFormatter

#options, #report_path

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ProgressFileFormatter

Returns a new instance of ProgressFileFormatter.



10
11
12
13
14
15
16
# File 'lib/ace/test_runner/formatters/progress_file_formatter.rb', line 10

def initialize(options = {})
  super
  @test_count = 0
  @line_width = options[:line_width] || 80
  @configuration = options
  @max_failures_to_display = options[:max_failures_to_display] || 7
end

Instance Method Details

#format_report(report) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/ace/test_runner/formatters/progress_file_formatter.rb', line 98

def format_report(report)
  # For CI, keep the report simple and parseable
  {
    status: report.success? ? "success" : "failure",
    stats: {
      total: report.result.total_tests,
      passed: report.result.passed,
      failed: report.result.failed,
      errors: report.result.errors,
      skipped: report.result.skipped,
      assertions: report.result.assertions,
      duration: report.result.duration
    },
    failures: report.result.failures_detail.map { |f| failure_summary(f) }
  }
end

#format_stdout(result) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ace/test_runner/formatters/progress_file_formatter.rb', line 18

def format_stdout(result)
  lines = []

  # Progress dots are printed during execution, ensure newline
  lines << "" if @test_count > 0

  # Report directory - use actual report path if available
  if @report_path
    lines << "Details: #{@report_path}/"
  elsif @configuration && @configuration[:save_reports]
    lines << "Details: #{@configuration[:report_dir] || ".ace-local/test/reports"}/latest/"
  end

  # Compact single-line summary with emoji status
  status = if result.success?
    ""
  elsif result.errors > 0
    "💥"
  else
    ""
  end

  summary = "#{status} #{result.total_tests} tests, #{result.assertions} assertions, " +
    "#{result.failed} failures, #{result.errors} errors (#{format_duration(result.duration)})"
  lines << summary

  # Add failure details if there are any
  if result.has_failures?
    lines << ""
    total_failures = result.failed + result.errors

    # Display up to max_failures_to_display failures
    failures_to_show = result.failures_detail.take(@max_failures_to_display)

    # Show failure count header with reference to full report if needed
    if total_failures > @max_failures_to_display
      report_path = @report_path || "#{@configuration[:report_dir] || ".ace-local/test/reports"}/latest"
      lines << "FAILURES (#{failures_to_show.size}/#{total_failures}) → #{report_path}/failures.json:"
    else
      lines << "FAILURES (#{total_failures}):"
    end

    failures_to_show.each_with_index do |failure, idx|
      # Extract file and line from location (e.g., "/path/file.rb:42:in `test_method'")
      if failure.location
        location_match = failure.location.match(/^([^:]+):(\d+)/)
        if location_match
          file = location_match[1].gsub(/^.*\/test\//, "test/")  # Shorten path
          line = location_match[2]
          location = "#{file}:#{line}"
        else
          location = failure.location
        end
      else
        location = failure.test_name || "unknown"
      end

      # Format: location - short message with individual failure report path
      message = truncate_message(failure.message, 60)
      lines << "  #{location} - #{message}"

      # Show individual failure report path if we have the report path
      if @report_path
        failure_filename = format("%03d-%s.md", idx + 1,
          failure.full_test_name.gsub(/\W+/, "_").downcase[0...50])
        lines << "  → Details: #{@report_path}/failures/#{failure_filename}"
      end
    end

    # If there are more failures than displayed
    if result.failures_detail.size > @max_failures_to_display
      remaining = result.failures_detail.size - @max_failures_to_display
      report_path = @report_path || "#{@configuration[:report_dir] || ".ace-local/test/reports"}/latest"
      lines << "  ... and #{remaining} more #{(remaining == 1) ? "failure" : "failures"}. See full report: #{report_path}/failures.json"
    end
  end

  lines.join("\n")
end

#on_finish(result) ⇒ Object



135
136
137
138
139
# File 'lib/ace/test_runner/formatters/progress_file_formatter.rb', line 135

def on_finish(result)
  # Ensure we're on a new line
  puts unless @test_count == 0 || @test_count % @line_width == 0
  puts format_stdout(result)
end

#on_start(total_files) ⇒ Object



115
116
117
118
# File 'lib/ace/test_runner/formatters/progress_file_formatter.rb', line 115

def on_start(total_files)
  # No verbose output in progress mode
  @test_count = 0
end

#on_test_complete(file, success, duration) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ace/test_runner/formatters/progress_file_formatter.rb', line 120

def on_test_complete(file, success, duration)
  # Print single character for each test file
  char = if success
    colorize(".", :green)
  else
    colorize("F", :red)
  end

  print char
  @test_count += 1

  # New line every N characters to prevent line overflow
  puts if @test_count % @line_width == 0
end