enhance(tests): 改进测试用例记录与覆盖率报告
- 在 ApiCase 中添加失败原因记录,提升测试结果的可读性 - 更新 CoverageReport 结构,增加总用例、通过用例和失败用例计数 - 优化 PrintCoverage 方法,支持详细输出未通过接口及其失败原因 - 更新 Swagger 生成逻辑,包含失败原因字段,增强调试信息 - 改进 SQL 错误计数逻辑,确保在测试模式下准确记录 SQL 错误
This commit is contained in:
+98
-29
@@ -31,20 +31,30 @@ type TestResponse struct {
|
||||
|
||||
// CoverageReport 覆盖率报告
|
||||
type CoverageReport struct {
|
||||
Total int
|
||||
Covered int
|
||||
Missing []string
|
||||
Details []MethodCoverage
|
||||
Total int
|
||||
Covered int
|
||||
Missing []string
|
||||
Details []MethodCoverage
|
||||
TotalCases int
|
||||
PassedCases int
|
||||
FailedCases int
|
||||
}
|
||||
|
||||
// MethodCoverage 单个接口的覆盖详情
|
||||
type MethodCoverage struct {
|
||||
Path string
|
||||
HasTest bool
|
||||
CaseCount int
|
||||
Passed int
|
||||
Failed int
|
||||
Duration time.Duration
|
||||
Path string
|
||||
HasTest bool
|
||||
CaseCount int
|
||||
Passed int
|
||||
Failed int
|
||||
Duration time.Duration
|
||||
FailedCases []FailedCase
|
||||
}
|
||||
|
||||
// FailedCase 失败用例信息
|
||||
type FailedCase struct {
|
||||
CaseName string
|
||||
FailReason string
|
||||
}
|
||||
|
||||
// TestRecord 单条测试记录
|
||||
@@ -64,6 +74,7 @@ type TestRecord struct {
|
||||
Note string
|
||||
ExpectResult interface{}
|
||||
VerifyError string
|
||||
FailReason string
|
||||
}
|
||||
|
||||
// TestCollector 线程安全的测试记录收集器
|
||||
@@ -106,6 +117,7 @@ func NewTestApp(configPath string, projects TestProj, listeners ...func(*Context
|
||||
os.Stderr = origStderr
|
||||
devNull.Close()
|
||||
|
||||
app.WebConnectLog = nil
|
||||
app.Log.SetOutput(io.Discard)
|
||||
|
||||
for _, lis := range listeners {
|
||||
@@ -272,6 +284,10 @@ func (that *TestApp) PrintCoverage() CoverageReport {
|
||||
mc.Passed++
|
||||
} else {
|
||||
mc.Failed++
|
||||
mc.FailedCases = append(mc.FailedCases, FailedCase{
|
||||
CaseName: r.CaseName,
|
||||
FailReason: r.FailReason,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,9 +296,53 @@ func (that *TestApp) PrintCoverage() CoverageReport {
|
||||
}
|
||||
}
|
||||
|
||||
// 汇总全部用例统计
|
||||
for _, d := range report.Details {
|
||||
report.TotalCases += d.CaseCount
|
||||
report.PassedCases += d.Passed
|
||||
report.FailedCases += d.Failed
|
||||
}
|
||||
|
||||
ranCount := len(visited)
|
||||
isPartialRun := ranCount > 0 && ranCount < report.Covered
|
||||
|
||||
// 分拣本次运行中通过/失败的接口
|
||||
var passedDetails, failedDetails []MethodCoverage
|
||||
for _, d := range report.Details {
|
||||
if !d.HasTest || d.CaseCount == 0 {
|
||||
continue
|
||||
}
|
||||
if isPartialRun && !visited[d.Path] {
|
||||
continue
|
||||
}
|
||||
if d.Failed > 0 {
|
||||
failedDetails = append(failedDetails, d)
|
||||
} else {
|
||||
passedDetails = append(passedDetails, d)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算本次运行的用例统计(部分运行时只统计实际运行的接口)
|
||||
ranInterfaces := len(failedDetails) + len(passedDetails)
|
||||
var ranTotalCases, ranPassedCases, ranFailedCases int
|
||||
if isPartialRun {
|
||||
for _, d := range failedDetails {
|
||||
ranTotalCases += d.CaseCount
|
||||
ranPassedCases += d.Passed
|
||||
ranFailedCases += d.Failed
|
||||
}
|
||||
for _, d := range passedDetails {
|
||||
ranTotalCases += d.CaseCount
|
||||
ranPassedCases += d.Passed
|
||||
ranFailedCases += d.Failed
|
||||
}
|
||||
} else {
|
||||
ranTotalCases = report.TotalCases
|
||||
ranPassedCases = report.PassedCases
|
||||
ranFailedCases = report.FailedCases
|
||||
ranInterfaces = len(failedDetails) + len(passedDetails)
|
||||
}
|
||||
|
||||
fmt.Println("\n========== API 测试覆盖率报告 ==========")
|
||||
if report.Total > 0 {
|
||||
fmt.Printf("总接口: %d | 已覆盖: %d | 覆盖率: %.1f%%\n",
|
||||
@@ -292,27 +352,36 @@ func (that *TestApp) PrintCoverage() CoverageReport {
|
||||
fmt.Println("总接口: 0")
|
||||
}
|
||||
|
||||
if !isPartialRun {
|
||||
var ranDetails []MethodCoverage
|
||||
for _, d := range report.Details {
|
||||
if d.HasTest && d.CaseCount > 0 {
|
||||
ranDetails = append(ranDetails, d)
|
||||
if isPartialRun && ranTotalCases > 0 {
|
||||
passRate := float64(ranPassedCases) / float64(ranTotalCases) * 100
|
||||
fmt.Printf("本次运行: %d 个接口 | 总用例: %d | 通过: %d | 未通过: %d | 通过率: %.1f%%\n",
|
||||
ranInterfaces, ranTotalCases, ranPassedCases, ranFailedCases, passRate)
|
||||
} else if ranTotalCases > 0 {
|
||||
passRate := float64(ranPassedCases) / float64(ranTotalCases) * 100
|
||||
fmt.Printf("总用例: %d | 通过: %d | 未通过: %d | 通过率: %.1f%%\n",
|
||||
ranTotalCases, ranPassedCases, ranFailedCases, passRate)
|
||||
}
|
||||
|
||||
if len(failedDetails) > 0 {
|
||||
fmt.Printf("\n---------- 未通过的接口 (%d个) ----------\n", len(failedDetails))
|
||||
for _, d := range failedDetails {
|
||||
fmt.Printf(" ✗ %s\t%d 用例 (%d 通过, %d 失败) %v\n",
|
||||
d.Path, d.CaseCount, d.Passed, d.Failed, d.Duration)
|
||||
for _, fc := range d.FailedCases {
|
||||
if fc.FailReason != "" {
|
||||
fmt.Printf(" [失败] %s — %s\n", fc.CaseName, fc.FailReason)
|
||||
} else {
|
||||
fmt.Printf(" [失败] %s\n", fc.CaseName)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ranDetails) > 0 {
|
||||
fmt.Println("\n本次运行:")
|
||||
for _, d := range ranDetails {
|
||||
fmt.Printf(" + %s\t%d 用例 (%d 通过, %d 失败) %v\n",
|
||||
d.Path, d.CaseCount, d.Passed, d.Failed, d.Duration)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("\n本次运行 %d 个接口:\n", ranCount)
|
||||
for _, d := range report.Details {
|
||||
if d.HasTest && d.CaseCount > 0 {
|
||||
fmt.Printf(" + %s\t%d 用例 (%d 通过, %d 失败) %v\n",
|
||||
d.Path, d.CaseCount, d.Passed, d.Failed, d.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
if len(passedDetails) > 0 {
|
||||
fmt.Println("\n---------- 通过的接口 ----------")
|
||||
for _, d := range passedDetails {
|
||||
fmt.Printf(" ✓ %s\t%d 用例 (%d 通过, %d 失败) %v\n",
|
||||
d.Path, d.CaseCount, d.Passed, d.Failed, d.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user