test: expose acceptance coverage metrics
This commit is contained in:
@@ -281,6 +281,56 @@ function derived(length, width, height, edge) {
|
||||
return { outerLength, outerWidth, outerHeight, volume: halfUp3(outerLength * outerWidth * outerHeight / 1_000_000) }
|
||||
}
|
||||
|
||||
export function buildAcceptanceSummary(steps = [], modules = [], coverageGaps = []) {
|
||||
const failed = steps.filter((step) => !step.passed).length
|
||||
const executedModules = modules.filter((module) => !module.skipped)
|
||||
const uniqueModuleNames = new Set(executedModules.map((module) => module.name).filter(Boolean))
|
||||
const uniqueRequestKeys = new Set()
|
||||
const uniqueStepNameSet = new Set()
|
||||
|
||||
for (const step of steps) {
|
||||
if (step.name) uniqueStepNameSet.add(step.name)
|
||||
const method = step.request?.method
|
||||
const path = step.request?.path
|
||||
if (!method || !path) continue
|
||||
uniqueRequestKeys.add(`${method}\u001f${path}\u001f${step.requestId || ''}`)
|
||||
}
|
||||
|
||||
const coverageGapStats = {
|
||||
total: coverageGaps.length,
|
||||
blocking: 0,
|
||||
nonBlocking: 0,
|
||||
byCategory: {},
|
||||
}
|
||||
for (const gap of coverageGaps) {
|
||||
const category = gap.category || 'uncategorized'
|
||||
const blocking = gap.blocking === true
|
||||
const categoryStats = coverageGapStats.byCategory[category]
|
||||
|| { total: 0, blocking: 0, nonBlocking: 0 }
|
||||
categoryStats.total += 1
|
||||
if (blocking) {
|
||||
coverageGapStats.blocking += 1
|
||||
categoryStats.blocking += 1
|
||||
} else {
|
||||
coverageGapStats.nonBlocking += 1
|
||||
categoryStats.nonBlocking += 1
|
||||
}
|
||||
coverageGapStats.byCategory[category] = categoryStats
|
||||
}
|
||||
|
||||
return {
|
||||
total: steps.length,
|
||||
passed: steps.length - failed,
|
||||
failed,
|
||||
moduleRuns: executedModules.length,
|
||||
uniqueModules: uniqueModuleNames.size,
|
||||
uniqueRequests: uniqueRequestKeys.size,
|
||||
uniqueStepNames: uniqueStepNameSet.size,
|
||||
skippedModules: modules.length - executedModules.length,
|
||||
coverageGaps: coverageGapStats,
|
||||
}
|
||||
}
|
||||
|
||||
export class AcceptanceRun {
|
||||
constructor(options) {
|
||||
this.options = options
|
||||
@@ -1141,13 +1191,13 @@ export class AcceptanceRun {
|
||||
this.addStep('report-security', '报告敏感信息扫描', null, !sensitive,
|
||||
sensitive ? '检测到密码、Token、二进制/base64 或 OCR 原文字段' : '未发现密码、Token、文件二进制/base64 或 OCR 原文字段')
|
||||
|
||||
const failed = this.steps.filter((step) => !step.passed).length
|
||||
const summary = buildAcceptanceSummary(this.steps, this.modules, this.coverageGaps)
|
||||
return {
|
||||
reportName: '后台管理测试环境 HTTP API 验收', marker: this.marker,
|
||||
gateway: this.options.gateway, overseasGateway: this.options.overseasGateway,
|
||||
generatedAt: new Date().toISOString(), startedAt: this.startedAt,
|
||||
success: this.fatal === null && failed === 0, fatal: this.fatal,
|
||||
summary: { total: this.steps.length, passed: this.steps.length - failed, failed },
|
||||
success: this.fatal === null && summary.failed === 0, fatal: this.fatal,
|
||||
summary,
|
||||
modules: this.modules, scenarios: this.scenarios, deploymentBlockers: this.deploymentBlockers,
|
||||
coverageGaps: this.coverageGaps,
|
||||
createdResources: this.createdResources,
|
||||
@@ -1169,7 +1219,7 @@ async function main() {
|
||||
await mkdir(dirname(outputPath), { recursive: true })
|
||||
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8')
|
||||
console.log(`REPORT=${outputPath}`)
|
||||
console.log(`RESULT=${report.success ? 'PASS' : 'FAIL'} total=${report.summary.total} passed=${report.summary.passed} failed=${report.summary.failed}`)
|
||||
console.log(`RESULT=${report.success ? 'PASS' : 'FAIL'} total=${report.summary.total} passed=${report.summary.passed} failed=${report.summary.failed} metric=assertions moduleRuns=${report.summary.moduleRuns} uniqueModules=${report.summary.uniqueModules} uniqueRequests=${report.summary.uniqueRequests} skippedModules=${report.summary.skippedModules}`)
|
||||
process.exitCode = report.success ? 0 : 1
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user