Execution metrics tell you how testing is progressing. Defect metrics tell you what testing is finding. While pass rates show how the test suite performed, defect trends reveal the underlying health of the software itself. A rising defect discovery rate late in the sprint might signal unstable code. A high reopen rate might signal incomplete fixes. A spike in production defects might signal gaps in pre-release testing. Learning to read these patterns is what transforms a junior tester who reports numbers into a senior QA engineer who predicts risks.
Key Defect Metrics and How to Read Trends
Defect metrics are most powerful when tracked over time as trends rather than as isolated snapshots. A single data point tells you where you are; a trend tells you where you are heading.
# Defect metrics with trend analysis across four sprints
sprint_defect_data = [
{"sprint": "Sprint 10", "found": 22, "fixed": 20, "reopened": 2,
"prod_defects": 3, "total_defects": 25, "critical": 4, "major": 8,
"minor": 7, "trivial": 3, "module_checkout": 10, "module_search": 5,
"module_auth": 4, "module_other": 3, "kloc_checkout": 5, "kloc_search": 8},
{"sprint": "Sprint 11", "found": 28, "fixed": 24, "reopened": 5,
"prod_defects": 4, "total_defects": 32, "critical": 6, "major": 10,
"minor": 9, "trivial": 3, "module_checkout": 14, "module_search": 6,
"module_auth": 4, "module_other": 4, "kloc_checkout": 5, "kloc_search": 8},
{"sprint": "Sprint 12", "found": 35, "fixed": 22, "reopened": 8,
"prod_defects": 6, "total_defects": 41, "critical": 9, "major": 12,
"minor": 10, "trivial": 4, "module_checkout": 18, "module_search": 7,
"module_auth": 5, "module_other": 5, "kloc_checkout": 6, "kloc_search": 8},
{"sprint": "Sprint 13", "found": 18, "fixed": 30, "reopened": 3,
"prod_defects": 2, "total_defects": 20, "critical": 2, "major": 6,
"minor": 7, "trivial": 3, "module_checkout": 8, "module_search": 4,
"module_auth": 3, "module_other": 3, "kloc_checkout": 6, "kloc_search": 8},
]
print("Defect Trend Analysis — Sprints 10-13")
print("=" * 70)
print(f"{'Sprint':<12} {'Found':>6} {'Fixed':>6} {'Reopen':>7} {'Leakage':>8} {'Reopen%':>8}")
print("-" * 70)
for s in sprint_defect_data:
leakage = (s["prod_defects"] / s["total_defects"]) * 100
reopen_rate = (s["reopened"] / s["fixed"]) * 100 if s["fixed"] > 0 else 0
print(f"{s['sprint']:<12} {s['found']:>6} {s['fixed']:>6} {s['reopened']:>7} "
f"{leakage:>7.1f}% {reopen_rate:>7.1f}%")
# Defect density by module (Sprint 12 example)
s12 = sprint_defect_data[2]
checkout_density = s12["module_checkout"] / s12["kloc_checkout"]
search_density = s12["module_search"] / s12["kloc_search"]
print(f"\n\nDefect Density (Sprint 12):")
print(f" Checkout: {s12['module_checkout']} defects / {s12['kloc_checkout']} KLOC = "
f"{checkout_density:.1f} defects/KLOC")
print(f" Search: {s12['module_search']} defects / {s12['kloc_search']} KLOC = "
f"{search_density:.1f} defects/KLOC")
print("\n\nTrend Interpretation:")
print(" Sprint 10-12: Discovery rising, fixes lagging → backlog growing")
print(" Sprint 12: Reopen rate spiked to 36% → incomplete fixes, root cause needed")
print(" Sprint 12: Leakage hit 14.6% → testing gaps, review coverage")
print(" Sprint 13: Discovery dropped, fixes outpaced → stabilisation working")
print(" Checkout module: 3.0 defects/KLOC → high-risk, needs design review")
Common Mistakes
Mistake 1 — Reporting defect metrics as isolated numbers without trend context
❌ Wrong: “We found 28 bugs this sprint.” (Is that high? Low? Improving? Worsening?)
✅ Correct: “We found 28 bugs this sprint, up from 22 last sprint. The increase is concentrated in the checkout module (14 vs 10 previously), which was refactored this sprint. This trend suggests the refactoring introduced instability.”
Mistake 2 — Ignoring the reopen rate
❌ Wrong: Not tracking how many defects are reopened after being marked as “Fixed.”
✅ Correct: “Our reopen rate spiked from 10% to 36% in Sprint 12, meaning over a third of fixes were incomplete. Root cause analysis shows that developers are not adding unit tests for their fixes, so the same logic error recurs. Action: require unit tests for all P1/P2 defect fixes.”