报告输出

基本信息

属性 值
包路径 com.gtnewhorizons.horizonqa.report(9 个类)
JUnit 报告器 report/JUnitXmlReporter.java
状态报告器 report/StatusJsonReporter.java
控制台报告器 report/ConsoleReporter.java
写入编排 report/RunReportWriter.java
原子写入 report/AtomicReportWriter.java
预检 report/ReportPathPreflight.java
结果模型 RunResult(record)、CaseResult(record)、IssueResult、RunResult
默认 JUnit 文件名 TEST-horizonqa.xml(HorizonQAProperties.java:27)
默认状态文件名 horizonqa-result.json(HorizonQAProperties.java:28)
JSON schema 版本 3(StatusJsonReporter.java:14)

功能

一轮测试结束后,Horizon-QA 写出两种机器可读报告,并可选择直接关服。

退出码

RunResult 定义三个退出码(RunResult.java:13-15):

退出码 常量 含义
0 EXIT_PASSED 全部通过
1 EXIT_REQUIRED_TEST_FAILURE 必需测试失败 / 超时
2 EXIT_INFRASTRUCTURE_ERROR 基础设施错误

ReportedRun.finish 在 exit 为真时打印一行汇总(必需的失败/超时数、未完成测试数、基础设施问题数), 然后调用 FMLCommonHandler.instance().exitJava(result.exitCode(), false) (ReportedRun.java:346-354)。是否关服由 -Dhorizonqa.stopServer 控制, 默认在 mode == ci && autoRun 时为真(HorizonQAProperties.java:432-435)。

JUnit XML

JUnitXmlReporter 写出标准 <testsuite> 文档(JUnitXmlReporter.java:15-31):

  • testsuite 的 tests 属性 = 用例数 + 问题数
  • failures / errors / skipped 取自 RunResult 的 junitFailures() / junitErrors() / junitSkipped()
  • time 为 durationSeconds(),格式 %.3f
  • timestamp 取 Instant.now() 并经 sanitizeAttr 处理
  • 用例逐个由 writeTestCase 写出,随后把每个 IssueResult 也作为一个 testcase 写出

hostname 固定为 localhost(JUnitXmlReporter.java:20)。

状态 JSON

StatusJsonReporter.toJson 生成的顶层字段(StatusJsonReporter.java:25-35):

字段 来源
schemaVersion 固定 3(StatusJsonReporter.java:14)
status result.status()
exitCode result.exitCode()
configuration appendConfiguration
计数块 appendCounts
报告路径块 appendReports
问题块 appendIssues
测试块 appendTests

写入保证

  • 原子写入:AtomicReportWriter.write(outputFile, tempFile -> ...) 先写临时文件再落位 (JUnitXmlReporter.java:16、StatusJsonReporter.java:17-21),避免半截报告
  • 写前预检:ReportPathPreflight 在写之前检查路径可用性
  • 控制台模式:RunReportWriter.writeConsole(result, LOG) 只打日志不落文件 (ReportedRun.java:341-342),用于不产出报告文件的运行

数值

数值名 值 来源
退出码种类 3(0 / 1 / 2) RunResult.java:13-15
JSON schema 版本 3 StatusJsonReporter.java:14
JUnit 默认文件名 TEST-horizonqa.xml HorizonQAProperties.java:27
状态默认文件名 horizonqa-result.json HorizonQAProperties.java:28
每 tick 秒数 0.05(TICKS_PER_SECOND = 20.0) CaseResult.java:27
report 包类数 9 ls src/main/java/com/gtnewhorizons/horizonqa/report/

报告路径解析

优先级自上而下(HorizonQAProperties.java:200-227):

  1. 显式 -Dhorizonqa.reportFile / -Dhorizonqa.statusFile —— 按该路径解析
  2. 仅有 -Dhorizonqa.reportDir —— 在该目录下拼默认文件名并 normalize()
  3. 都没有 —— 默认文件名落在 System.getProperty("user.dir", ".") 下

CaseResult 字段

CaseResult 是 record,字段(CaseResult.java:17-19):

id classname name status required tickCount timeSeconds failureMessage failureType failureTrace outputLines blockedByIssueId

其中 outputLines 承载测试期间记录的事件行,blockedByIssueId 为空时归一化为空字符串 (CaseResult.java:30)。RunResult 的字段为 mode cases issues junitReport(RunResult.java:11),其中 mode 与 junitReport 为 null 时归一化为空字符串(RunResult.java:18-19)。

交互

报告在 ReportedRun.finish 中写出(ReportedRun.java:332-345),顺序为:

  1. invokeOwedAfterHooks() — 补跑欠下的 @AfterBatch 钩子
  2. releaseChunks() — 释放强制加载的区块
  3. 汇总 RunResult
  4. 写文件(或仅写控制台)
  5. publish(result) — 发布结果供 /horizonqa runfailed 读取
  6. 若 exit 为真则关服

/horizonqa runfailed 正是读取 ReportedRun.lastResult(),把 failed() / timedOut() / error() 为真的用例 id 收集成重跑集合(HorizonQACommand.java:441-450)。

相关条目