K1Guitar/tools/k1_harness/report/markdown.py

78 lines
3.0 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""统一测试报告PASS/FAIL/SKIP/SENT 四态 + Markdown 输出 + 退出码."""
from __future__ import annotations
import os
from dataclasses import dataclass, field
from datetime import datetime
STATUSES = ("PASS", "FAIL", "SKIP", "SENT")
@dataclass
class CaseResult:
suite: str
name: str
status: str
detail: str = ""
@dataclass
class HarnessReport:
title: str = "K1 HIL 自动化测试报告"
cases: list[CaseResult] = field(default_factory=list)
notes: list[str] = field(default_factory=list)
started: datetime = field(default_factory=datetime.now)
def add(self, suite: str, name: str, status: str, detail: str = "") -> None:
status = status.upper()
assert status in STATUSES, f"bad status {status}"
self.cases.append(CaseResult(suite, name, status, detail))
print(f"[{status:>4}] {suite}/{name}" + (f" | {detail}" if detail else ""), flush=True)
def extend_rows(self, suite: str, rows) -> None:
"""吸收 test_protocol_app_sim.Results 风格的 (name, status, detail) 行."""
for name, status, detail in rows:
self.add(suite, name, status, detail)
def counts(self) -> dict:
return {s: sum(1 for c in self.cases if c.status == s) for s in STATUSES}
def exit_code(self) -> int:
return 1 if self.counts()["FAIL"] else 0
def summary_text(self) -> str:
n = self.counts()
return f"PASS={n['PASS']} FAIL={n['FAIL']} SKIP={n['SKIP']} SENT={n['SENT']}"
def print_summary(self) -> None:
print("\n===== 汇总 =====", flush=True)
for suite in dict.fromkeys(c.suite for c in self.cases):
sub = [c for c in self.cases if c.suite == suite]
n = {s: sum(1 for c in sub if c.status == s) for s in STATUSES}
print(f" {suite:<12} PASS={n['PASS']} FAIL={n['FAIL']} SKIP={n['SKIP']} SENT={n['SENT']}", flush=True)
print(f" {'TOTAL':<12} {self.summary_text()}", flush=True)
for c in self.cases:
if c.status == "FAIL":
print(f" FAIL: {c.suite}/{c.name} | {c.detail}", flush=True)
def write_markdown(self, path: str) -> str:
os.makedirs(os.path.dirname(os.path.abspath(path)), exist_ok=True)
lines = [
f"# {self.title}",
"",
f"- 时间: {self.started.isoformat(timespec='seconds')}",
f"- 结果: {self.summary_text()}",
]
for note in self.notes:
lines.append(f"- {note}")
lines += ["", "| 套件 | 用例 | 结果 | 详情 |", "|------|------|------|------|"]
for c in self.cases:
detail = c.detail.replace("|", "\\|").replace("\n", " ")
lines.append(f"| {c.suite} | {c.name} | {c.status} | {detail} |")
lines.append("")
with open(path, "w", encoding="utf-8", newline="\n") as f:
f.write("\n".join(lines))
print(f"报告已保存: {os.path.abspath(path)}", flush=True)
return path