Module: Coatepec::Spec::Result

Defined in:
lib/coatepec/spec/result.rb

Overview

Turns a finished RSpec child process's exit status, captured stdout/stderr (each capped at MAX_OUTPUT_BYTES), and RSpec's own JSON formatter output into the flat result hash rails_spec_run returns.

Constant Summary collapse

MAX_OUTPUT_BYTES =
256 * 1024

Class Method Summary collapse

Class Method Details

.base(pid, status, stdout_result, stderr_result) ⇒ Object

rubocop:disable Metrics/MethodLength -- one flat hash literal mapping Process::Status/captured-output fields to the result payload's own field names; splitting it would scatter that 1:1 mapping across methods for no readability gain.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/coatepec/spec/result.rb', line 30

def base(pid, status, stdout_result, stderr_result)
  {
    status: status.exited? && status.exitstatus.zero? ? "passed" : "failed",
    exit_code: status.exitstatus,
    child_pid: pid,
    signaled: status.signaled?,
    termsig: status.termsig,
    stopsig: status.stopsig,
    coredump: status.respond_to?(:coredump?) ? status.coredump? : false,
    stdout: stdout_result[:text],
    stdout_truncated: stdout_result[:truncated],
    stderr: stderr_result[:text],
    stderr_truncated: stderr_result[:truncated]
  }
end

.build(pid:, status:, out_r:, err_r:, json_path:) ⇒ Object



15
16
17
18
19
20
21
22
23
24
# File 'lib/coatepec/spec/result.rb', line 15

def build(pid:, status:, out_r:, err_r:, json_path:)
  stdout_result = read_bounded(out_r)
  stderr_result = read_bounded(err_r)
  summary = read_summary(json_path)

  base(pid, status, stdout_result, stderr_result).merge(
    summary: summary && summary_fields(summary),
    examples: (summary&.fetch("examples", []) || []).first(500).map { |e| example_fields(e) }
  )
end

.example_fields(example) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/coatepec/spec/result.rb', line 61

def example_fields(example)
  {
    id: example["id"],
    description: example["full_description"],
    status: example["status"],
    file_path: example["file_path"],
    line_number: example["line_number"]
  }
end

.read_bounded(io) ⇒ Object



71
72
73
74
75
76
# File 'lib/coatepec/spec/result.rb', line 71

def read_bounded(io)
  data = io.read.to_s
  truncated = data.bytesize > MAX_OUTPUT_BYTES
  data = data.byteslice(-MAX_OUTPUT_BYTES, MAX_OUTPUT_BYTES) if truncated
  { text: data, truncated: truncated }
end

.read_summary(json_path) ⇒ Object

rubocop:enable Metrics/MethodLength



47
48
49
50
51
# File 'lib/coatepec/spec/result.rb', line 47

def read_summary(json_path)
  return nil unless File.exist?(json_path) && !File.empty?(json_path)

  JSON.parse(File.read(json_path))
end

.summary_fields(summary) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/coatepec/spec/result.rb', line 53

def summary_fields(summary)
  {
    example_count: summary.dig("summary", "example_count"),
    failure_count: summary.dig("summary", "failure_count"),
    duration: summary.dig("summary", "duration")
  }
end