Reports and CI/CD Integration
The ucis.ncdb.reports and ucis.ncdb.testplan_export modules
provide structured reports for testplan closure, regression delta, and
CI/CD export. Every report function returns a typed dataclass with a
to_json() method; companion format_*() functions render the
dataclass to human-readable text.
Closure and gate reports
from ucis.ncdb.ncdb_ucis import NcdbUCIS
from ucis.ncdb.testplan import get_testplan
from ucis.ncdb.testplan_closure import compute_closure
from ucis.ncdb.reports import (
report_testpoint_closure,
format_testpoint_closure,
report_stage_gate,
format_stage_gate,
)
db = NcdbUCIS("coverage.cdb")
plan = get_testplan(db)
results = compute_closure(plan, db)
# Print the closure table
summary = report_testpoint_closure(results)
print(format_testpoint_closure(summary))
# Evaluate a stage gate
gate = report_stage_gate(results, "V2", plan)
print(format_stage_gate(gate))
# Machine-readable JSON
import json
data = json.loads(summary.to_json())
Stage-rollup output example:
Testpoint Stage Status Pass Fail
----------------------------------------------------------------
uart_reset V1 ✓ CLOSED 5 0
uart_loopback V2 ✗ FAILING 0 3
----------------------------------------------------------------
Stage roll-up:
V1 [████████████████████] 1/1 (100.0%)
V2 [░░░░░░░░░░░░░░░░░░░░] 0/1 (0.0%)
Total: 1/2 closed (0 N/A)
Regression delta
Compare two closure result sets to find testpoints that changed status between runs:
from ucis.ncdb.reports import report_regression_delta, format_regression_delta
# Load two snapshots
results_baseline = compute_closure(plan, db_baseline)
results_current = compute_closure(plan, db_current)
delta = report_regression_delta(results_current, results_baseline)
print(format_regression_delta(delta))
# Regression delta: +1 closed, -0 newly failing, 1 still open
# Machine-readable
print(delta.to_json())
Reliability report
Compute per-testpoint flake scores from v2 history data:
from ucis.ncdb.reports import report_testpoint_reliability, format_testpoint_reliability
report = report_testpoint_reliability(results, db)
print(format_testpoint_reliability(report))
Output example:
Testpoint Flake Pass Fail
--------------------------------------------------------
uart_loopback 0.800 2 8 ⚠
uart_reset 0.000 10 0
Unexercised covergroups
Identify zero-hit or low-coverage covergroups:
from ucis.ncdb.reports import (
report_unexercised_covergroups,
format_unexercised_covergroups,
)
report = report_unexercised_covergroups(db, plan, low_threshold=50.0)
print(format_unexercised_covergroups(report))
Coverage contribution
Show which tests contribute the most unique coverage bins (requires v2 history with contribution data):
from ucis.ncdb.reports import (
report_coverage_contribution,
format_coverage_contribution,
)
report = report_coverage_contribution(db)
print(format_coverage_contribution(report))
JUnit XML export
Export closure results as a JUnit XML file for CI dashboards:
from ucis.ncdb.testplan_export import export_junit_xml
export_junit_xml(results, "closure_results.xml")
Or via the CLI:
pyucis testplan export-junit coverage.cdb --out closure_results.xml
The XML maps each testpoint to a <testcase> element. FAILING and
PARTIAL testpoints become <failure> elements; NOT_RUN becomes
<skipped>.
GitHub Annotations
Emit GitHub Actions workflow commands for inline PR annotations:
from ucis.ncdb.testplan_export import export_github_annotations
export_github_annotations(results) # writes to stdout
# Or capture to a string
import io
buf = io.StringIO()
export_github_annotations(results, output=buf)
print(buf.getvalue())
In a GitHub Actions workflow:
- name: Compute closure
run: |
python -c "
from ucis.ncdb.ncdb_ucis import NcdbUCIS
from ucis.ncdb.testplan import get_testplan
from ucis.ncdb.testplan_closure import compute_closure
from ucis.ncdb.testplan_export import export_github_annotations
db = NcdbUCIS('coverage.cdb')
plan = get_testplan(db)
results = compute_closure(plan, db)
export_github_annotations(results)
"
Test budget by stage
Estimate CPU-hour cost per stage from v2 test history mean CPU times:
from ucis.ncdb.ncdb_ucis import NcdbUCIS
from ucis.ncdb.testplan import get_testplan
from ucis.ncdb.reports import report_test_budget, format_test_budget
db = NcdbUCIS("coverage.cdb")
plan = db.getTestplan()
rpt = report_test_budget(plan, db)
print(format_test_budget(rpt))
# JSON export
import json
print(json.loads(rpt.to_json())["stage_totals"])
Testpoints whose tests have no CPU time recorded appear in
rpt.missing_stats.
Safety traceability matrix
Build a requirement-to-testpoint matrix (suitable for safety audits):
from ucis.ncdb.reports import report_safety_matrix, format_safety_matrix
rpt = report_safety_matrix(results) # results from compute_closure
print(format_safety_matrix(rpt))
# CSV for a spreadsheet or audit tool
with open("traceability.csv", "w") as f:
f.write(rpt.to_csv())
# Add a WaiverSet to flag waived testpoints
from ucis.ncdb.waivers import WaiverSet
waivers = WaiverSet.from_file("waivers.hjson")
rpt = report_safety_matrix(results, waivers=waivers)
Seed reliability heat-map
Identify seeds that are disproportionately flaky:
from ucis.ncdb.ncdb_ucis import NcdbUCIS
from ucis.ncdb.reports import report_seed_reliability, format_seed_reliability
db = NcdbUCIS("coverage.cdb")
rpt = report_seed_reliability(db, "uart_smoke")
print(format_seed_reliability(rpt))
# Seeds with flake_score ≥ 0.2 are flagged with ⚠
# JSON heat-map for a custom dashboard
import json
data = json.loads(rpt.to_json())
for row in data["rows"]:
if row["flake"] >= 0.2:
print(f"Seed {row['seed']}: {row['fail']} failures")
GitHub Step Summary
Write a markdown table to $GITHUB_STEP_SUMMARY:
import os
from ucis.ncdb.testplan_export import export_summary_markdown
md = export_summary_markdown(results, stage_gate=gate)
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as f:
f.write(md)
The output includes a stage roll-up table, per-testpoint status rows, and (when stage_gate is supplied) a gate verdict with a list of blocking testpoints.
API reference
- ucis.ncdb.reports.report_testpoint_closure(results: List[TestpointResult]) ClosureSummary
Compute a closure summary from testpoint results.
- Parameters:
results – List of
TestpointResultobjects (output ofcompute_closure()).- Returns:
ClosureSummarywith per-stage roll-up and totals.
- ucis.ncdb.reports.format_testpoint_closure(summary: ClosureSummary, *, show_all: bool = False) str
Render a
ClosureSummaryas a terminal table.- Parameters:
summary – Output of
report_testpoint_closure().show_all – If False (default), skip N/A and UNIMPLEMENTED rows.
- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.ClosureSummary(results: List[TestpointResult], by_stage: Dict[str, Dict], total_closed: int, total_na: int, total: int)
Result of
report_testpoint_closure().- Parameters:
results – Per-testpoint closure results.
by_stage – Stage-level roll-up: stage → {closed, total, pct}.
total_closed – Number of testpoints with status CLOSED.
total_na – Number of testpoints with status N/A.
total – Total testpoint count.
- ucis.ncdb.reports.report_stage_gate(results: List[TestpointResult], stage: str, testplan: Testplan, require_flake_score_below: float | None = None, require_coverage_pct: float | None = None) StageGateReport
Evaluate a stage gate (go/no-go for advancing to next stage).
- Parameters:
results – Output of
compute_closure().stage – Target stage to evaluate (
"V1","V2", etc.).testplan – The
Testplanbeing evaluated.require_flake_score_below – Optional flake threshold (0–1).
require_coverage_pct – Optional minimum coverage percentage.
- Returns:
- ucis.ncdb.reports.format_stage_gate(report: StageGateReport) str
Render a
StageGateReportas a terminal summary.- Parameters:
report – Output of
report_stage_gate().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.StageGateReport(stage: str, passed: bool, blocking: List[TestpointResult], message: str, gate_detail: dict)
Result of
report_stage_gate().- Parameters:
stage – Target stage (e.g.
"V2").passed – Whether the gate passes.
blocking – Testpoints that are not yet CLOSED (and not N/A).
message – Human-readable verdict line.
gate_detail – Raw detail dict from
stage_gate_status().
- ucis.ncdb.reports.report_regression_delta(results_new: List[TestpointResult], results_old: List[TestpointResult]) RegressionDelta
Compute the testplan closure delta between two regression runs.
- Parameters:
results_new – Closure results for the current regression.
results_old – Closure results for the baseline regression.
- Returns:
- ucis.ncdb.reports.format_regression_delta(report: RegressionDelta) str
Render a
RegressionDeltaas a terminal summary.- Parameters:
report – Output of
report_regression_delta().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.RegressionDelta(newly_closed: List[TestpointResult], newly_failing: List[TestpointResult], unchanged_open: List[TestpointResult], summary: str)
Delta between two closure result sets.
- Parameters:
newly_closed – Testpoints that moved to CLOSED.
newly_failing – Testpoints that were not FAILING but are now.
unchanged_open – Testpoints that remain open/partial.
summary – One-line summary string.
- ucis.ncdb.reports.report_testpoint_reliability(results: List[TestpointResult], db, flaky_threshold: float = 0.2) TestpointReliability
Compute per-testpoint flake scores from v2 test_stats.
- Parameters:
results – Output of
compute_closure().db – An open
NcdbUCISinstance.flaky_threshold – Flake score above which a testpoint is flagged.
- Returns:
- ucis.ncdb.reports.format_testpoint_reliability(report: TestpointReliability) str
Render a
TestpointReliabilityas a terminal table.- Parameters:
report – Output of
report_testpoint_reliability().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.TestpointReliability(rows: List[Tuple[str, float, int, int]], flaky_threshold: float = 0.2)
Per-testpoint flake scores.
- Parameters:
rows – List of (testpoint_name, flake_score, pass_count, fail_count). Sorted by flake_score descending.
flaky_threshold – Score above which a testpoint is considered flaky.
- ucis.ncdb.reports.report_unexercised_covergroups(db, testplan: Testplan, low_threshold: float = 50.0) UnexercisedCovergroups
Identify covergroups with zero or low coverage.
- Parameters:
db – An open UCIS database.
testplan – The active testplan (used to filter to plan-tracked groups).
low_threshold – Percentage below which a covergroup is flagged as low-hit (default 50%).
- Returns:
- ucis.ncdb.reports.format_unexercised_covergroups(report: UnexercisedCovergroups) str
Render an
UnexercisedCovergroupsreport as terminal text.- Parameters:
report – Output of
report_unexercised_covergroups().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.UnexercisedCovergroups(zero_hit: List[str], low_hit: List[Tuple[str, float]], threshold: float = 50.0)
Covergroups with zero hits.
- Parameters:
zero_hit – List of covergroup names with 0% coverage.
low_hit – List of (name, pct) tuples with 0 < pct < threshold.
threshold – Low-hit threshold used.
- ucis.ncdb.reports.report_coverage_contribution(db) CoverageContribution
Report per-test unique coverage bin contribution from v2 contrib data.
- Parameters:
db – An open
NcdbUCISinstance.- Returns:
- ucis.ncdb.reports.format_coverage_contribution(report: CoverageContribution) str
Render a
CoverageContributionas a terminal table.- Parameters:
report – Output of
report_coverage_contribution().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.CoverageContribution(rows: List[Tuple[str, int, int]], total_bins: int)
Per-test unique bin contribution.
- Parameters:
rows – List of (test_name, unique_bins, total_hits) sorted by unique_bins descending.
total_bins – Total covered bins in the database.
- ucis.ncdb.reports.report_test_budget(testplan: Testplan, db) TestBudget
Estimate CPU-hour budget per stage from v2 test_stats mean CPU times.
For each testpoint the mean CPU time of all its mapped tests is summed. Testpoints with no CPU stats are listed in
missing_stats.- Parameters:
testplan – The active
Testplan.db – An open
NcdbUCISinstance.
- Returns:
- ucis.ncdb.reports.format_test_budget(report: TestBudget) str
Render a
TestBudgetas a terminal table.- Parameters:
report – Output of
report_test_budget().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.TestBudget(rows: List[Tuple[str, str, float, int]], stage_totals: Dict[str, float], missing_stats: List[str])
CPU time budget by stage.
- Parameters:
rows – List of (stage, testpoint_name, mean_cpu_sec, total_runs) sorted by stage rank then mean_cpu_sec descending.
stage_totals – Mapping of stage → total estimated CPU seconds.
missing_stats – Testpoint names for which no CPU stats are available.
- ucis.ncdb.reports.report_safety_matrix(results: List[TestpointResult], waivers=None) SafetyMatrix
Build a requirement to testpoint traceability matrix.
- Parameters:
results – Output of
compute_closure().waivers – Optional
WaiverSet.
- Returns:
- ucis.ncdb.reports.format_safety_matrix(report: SafetyMatrix) str
Render a
SafetyMatrixas a text table.- Parameters:
report – Output of
report_safety_matrix().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.SafetyMatrix(rows: List[Tuple[str, str, str, str, bool]], untested_requirements: List[str])
Requirement x testpoint traceability matrix with waiver flags.
- Parameters:
rows – List of (req_id, req_desc, testpoint_name, status, waived).
untested_requirements – Requirement IDs with no linked testpoints.
- ucis.ncdb.reports.report_seed_reliability(db, test_name: str) SeedReliability
Compute per-seed pass/fail counts from v2 history buckets.
- Parameters:
db – An open
NcdbUCISinstance.test_name – Name of the test to analyse.
- Returns:
- ucis.ncdb.reports.format_seed_reliability(report: SeedReliability) str
Render a
SeedReliabilityas a terminal heat-map table.- Parameters:
report – Output of
report_seed_reliability().- Returns:
Human-readable multiline string.
- class ucis.ncdb.reports.SeedReliability(test_name: str, rows: List[Tuple[int, int, int, float]], total_seeds: int)
Per-seed pass/fail counts for a given test name.
- Parameters:
test_name – The queried test name.
rows – List of (seed_id, pass_count, fail_count, flake_score) sorted by fail_count descending.
total_seeds – Total unique seeds seen.
- ucis.ncdb.testplan_export.export_junit_xml(results: List[TestpointResult], output_path: str, suite_name: str = 'testplan_closure') None
Write closure results as a JUnit XML file.
Each testpoint becomes a
<testcase>. Testpoints with status FAILING or PARTIAL get a<failure>element; NOT_RUN gets a<skipped>element; CLOSED is a plain pass.- Parameters:
results – Output of
compute_closure().output_path – Destination
.xmlfile path.suite_name – Value of the
nameattribute on<testsuite>.
Example:
from ucis.ncdb.testplan_export import export_junit_xml export_junit_xml(results, "closure_results.xml")
- ucis.ncdb.testplan_export.export_github_annotations(results: List[TestpointResult], file: str = 'testplan', *, output=None) None
Write GitHub Actions workflow command annotations to output.
FAILING testpoints emit
::error::lines; PARTIAL and NOT_RUN emit::warning::lines. CLOSED and N/A produce no output.- Parameters:
results – Output of
compute_closure().file – Value used in the
file=annotation field (defaults to"testplan").output – File-like object to write to (defaults to
sys.stdout).
Example:
from ucis.ncdb.testplan_export import export_github_annotations export_github_annotations(results) # writes to stdout
- ucis.ncdb.testplan_export.export_summary_markdown(results: List[TestpointResult], stage_gate: StageGateReport | None = None, history_db=None) str
Generate a GitHub Actions Job Summary–compatible markdown string.
- Parameters:
results – Output of
compute_closure().stage_gate – Optional
StageGateReportto include a gate verdict section.history_db – Unused; reserved for future trend lines.
- Returns:
A markdown string suitable for appending to
$GITHUB_STEP_SUMMARY.
Example:
from ucis.ncdb.testplan_export import export_summary_markdown md = export_summary_markdown(results, stage_gate=gate) with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as f: f.write(md)
See also
Testplan Integration — Testplan format and closure computation
Test History — Binary test history API