Class: Bparity::Reporting::Reporter

Inherits:
Object
  • Object
show all
Defined in:
lib/bparity/reporting.rb

Constant Summary collapse

FORMATS =
%w[markdown json junit html].freeze

Instance Method Summary collapse

Constructor Details

#initialize(results, bundle: nil) ⇒ Reporter

Returns a new instance of Reporter.



38
39
40
41
# File 'lib/bparity/reporting.rb', line 38

def initialize(results, bundle: nil)
  @results = results
  @bundle = bundle
end

Instance Method Details

#htmlObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/bparity/reporting.rb', line 97

def html
  rows = @results.map do |result|
    details = CGI.escapeHTML(JSON.pretty_generate(result.differences))
    "<tr><td>#{result.status.to_s.upcase}</td><td>#{CGI.escapeHTML(result.id)}</td>" \
      "<td><pre>#{details}</pre></td></tr>"
  end.join
  data = summary
  matrix = matrix_html(data.fetch("assurance_matrix"))
  assessment = CGI.escapeHTML(JSON.pretty_generate(data.fetch("five_point_assessment")))
  "<!doctype html><html lang=\"en\"><meta charset=\"utf-8\"><title>bparity report</title>" \
    "<h1>bparity conformance report</h1>#{matrix}<h2>Five-point assessment</h2><pre>#{assessment}</pre>" \
    "<table><thead><tr><th>Status</th><th>ID</th><th>Details</th></tr>" \
    "</thead><tbody>#{rows}</tbody></table></html>"
end

#jsonObject



53
# File 'lib/bparity/reporting.rb', line 53

def json = JSON.pretty_generate(summary)

#junitObject



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/bparity/reporting.rb', line 83

def junit
  failures = @results.count { |result| result.status == :fail }
  cases = @results.map do |result|
    failure = if result.status == :fail
                details = CGI.escapeHTML(JSON.generate(result.differences))
                "<failure message=\"Behavior differs\">#{details}</failure>"
              end
    "<testcase name=\"#{CGI.escapeHTML(result.id)}\">#{failure}</testcase>"
  end.join
  header = %(<?xml version="1.0" encoding="UTF-8"?>)
  suite = %(<testsuite tests="#{@results.length}" failures="#{failures}">#{cases}</testsuite>)
  header + suite
end

#markdownObject



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
# File 'lib/bparity/reporting.rb', line 55

def markdown
  data = summary
  lines = ["# bparity conformance report", "",
           "Total: #{data['total']} | PASS: #{data['pass']} | " \
           "FAIL: #{data['fail']} | WAIVED: #{data['waived']} | SKIPPED: #{data['skipped']}", ""]
  @results.each do |result|
    lines << "- **#{result.status.to_s.upcase}** `#{result.id}` #{result.description}"
    if result.waiver
      lines << "  - Waiver: #{result.waiver.reason} " \
               "(approved by #{result.waiver.approved_by} on #{result.waiver.approved_at})"
    end
    result.differences.each do |difference|
      lines << "  - `#{difference['path']}` expected `#{difference['expected'].inspect}`, " \
               "got `#{difference['actual'].inspect}`"
    end
  end
  assessment = data.fetch("five_point_assessment")
  unless assessment.empty?
    lines.push("", "## Five-point assessment", "",
               "1. Specification coverage: #{assessment.fetch('specification_coverage')}",
               "2. Generated checks: #{assessment.fetch('generated_checks')}",
               "3. Formal assurance: #{JSON.generate(assessment.fetch('formal_assurance'))}",
               "4. Constraint strength: #{assessment.fetch('constraint_strength').fetch('status')}",
               "5. Residual risks: #{residual_risks(assessment)}")
  end
  lines.join("\n")
end

#summaryObject



43
44
45
46
47
48
49
50
51
# File 'lib/bparity/reporting.rb', line 43

def summary
  counts = @results.group_by(&:status).transform_values(&:count)
  { "total" => @results.count, "pass" => counts.fetch(:pass, 0), "fail" => counts.fetch(:fail, 0),
    "waived" => counts.fetch(:waived, 0), "skipped" => counts.fetch(:skipped, 0),
    "results" => @results.map(&:to_h),
    "assumptions" => @bundle&.fetch("verification_assumptions", []),
    "assurance_matrix" => @bundle ? AssuranceMatrix.new(@bundle).to_h : {},
    "five_point_assessment" => @bundle ? Adequacy::Analyzer.new(bundle: @bundle, results: @results).call : {} }
end