1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! # Test Coverage and Test Effectiveness
//!
//! **Test coverage** measures the percentage of code executed by a test
//! suite — line, branch, or path coverage. It is cheap to compute and easy
//! to visualize as a single percentage, which also makes it one of the most
//! frequently gamed metrics in software engineering: coverage measures
//! whether code executed during a test run, not whether the test actually
//! checked that the code behaved correctly. **Mutation testing** answers
//! that gap directly: it deliberately introduces small, artificial faults
//! into the code and checks whether the test suite catches ("kills") them,
//! and is coverage's necessary complement, not an optional extra.
//!
//! ## Formula
//!
//! ```text
//! Test coverage % = lines (or branches) covered / total lines × 100
//! Mutation kill rate % = mutants killed / mutants total × 100
//!
//! covered / killed = execution or detection count
//! total = denominator (lines, branches, or mutants); zero is undefined
//! ```
//!
//! ## Why it matters
//!
//! A coverage target with no effectiveness check is a textbook Goodhart's
//! law setup: the number improves while genuine quality does not. A test
//! suite with high line coverage but a low mutation-kill rate is executing
//! code without meaningfully checking it — pairing the two is the single
//! most effective guardrail against coverage-target gaming.
//!
//! ## Example
//!
//! The topic doc's enterprise example: a company-wide 95% coverage
//! requirement, enforced as a hard CI gate, coexisted with a mutation-kill
//! rate under 40% across much of the codebase — tests executed code without
//! meaningfully asserting on its behaviour. The revised policy required an
//! 80% mutation-kill-rate threshold for payment and authentication code.
//!
//! ```rust
//! use software_engineering::test_effectiveness::{
//! mutation_kill_rate_percent, test_coverage_percent,
//! };
//!
//! // A company-wide "95% coverage requirement" met at face value...
//! let coverage = test_coverage_percent(95.0, 100.0);
//! assert_eq!(coverage, Some(95.0));
//!
//! // ...while the mutation-kill rate is "under 40%" on the same code —
//! // high coverage, weak verification.
//! let kill_rate = mutation_kill_rate_percent(38.0, 100.0).unwrap();
//! assert!(kill_rate < 40.0);
//!
//! // The revised policy's "80% kill-rate threshold" for critical code.
//! let critical_kill_rate = mutation_kill_rate_percent(85.0, 100.0).unwrap();
//! assert!(critical_kill_rate >= 80.0);
//!
//! // An empty denominator leaves both rates undefined.
//! assert_eq!(test_coverage_percent(1.0, 0.0), None);
//! assert_eq!(mutation_kill_rate_percent(1.0, 0.0), None);
//! ```
//!
//! ## Pitfalls
//!
//! - **Treating coverage percentage as a direct quality verdict** — it
//! measures execution, not verification.
//! - **Writing tests primarily to satisfy a coverage gate**, producing the
//! threshold-gaming pattern a coverage-only target invites.
//! - **Disabling or deleting failing tests** instead of fixing the
//! underlying problem, which removes real protection while the reported
//! number barely moves.
//! - **Applying a uniform coverage target regardless of code risk**, wasting
//! effort on low-risk code and under-investing in critical paths.
//! - **Treating a coverage-mutation gap as evidence of nothing**: a large
//! gap between a high coverage number and a low mutation-kill rate is the
//! clearest sign that coverage alone is not telling you what you think.
//!
//! ## Sources
//!
//! - Chapter 4.2, Test coverage and test effectiveness.
//! - Jia, Yue, and Mark Harman, "An Analysis and Survey of the Development
//! of Mutation Testing," *IEEE Transactions on Software Engineering*
//! (2011).
//!
//! Topic doc: software-engineering-metrics/locales/en-001/chapters/04-02-test-coverage-and-test-effectiveness.md
/// Test coverage as a percentage: covered lines (or branches) / total × 100.
///
/// Coverage measures whether code executed during a test run, not whether
/// the test meaningfully verified its behaviour. Use it to find untested
/// code (a floor), not as a ceiling to maximize; pair it with
/// [`mutation_kill_rate_percent`] to check that the covered code is actually
/// being verified.
///
/// # Arguments
///
/// * `covered` — lines, branches, or paths executed by the test suite.
/// * `total` — total lines, branches, or paths in the measured code.
///
/// # Returns
///
/// `Some(percentage)` (e.g. `95.0` for 95%), or `None` when `total` is zero
/// (coverage undefined — there is no code to cover).
///
/// # Examples
///
/// ```rust
/// use software_engineering::test_effectiveness::test_coverage_percent;
///
/// // A company-wide 95% coverage requirement, met at face value.
/// assert_eq!(test_coverage_percent(95.0, 100.0), Some(95.0));
/// assert_eq!(test_coverage_percent(1.0, 0.0), None);
/// ```
/// Mutation kill rate as a percentage: mutants killed / mutants total × 100.
///
/// Mutation testing introduces small, artificial faults (flipping a
/// comparison operator, changing a boundary condition) and checks whether
/// the test suite fails against each mutated version. A high kill rate
/// means the tests are genuinely verifying behaviour, not merely executing
/// it; this is the check on test effectiveness itself, and coverage's
/// necessary complement.
///
/// # Arguments
///
/// * `mutants_killed` — mutants the test suite detected (caused a failure).
/// * `mutants_total` — total mutants generated and run against the suite.
///
/// # Returns
///
/// `Some(percentage)`, or `None` when `mutants_total` is zero (no mutants
/// were generated — kill rate undefined).
///
/// # Examples
///
/// ```rust
/// use software_engineering::test_effectiveness::mutation_kill_rate_percent;
///
/// // High coverage paired with a kill rate "under 40%": tests execute
/// // code without meaningfully checking it.
/// let kill_rate = mutation_kill_rate_percent(38.0, 100.0).unwrap();
/// assert!(kill_rate < 40.0);
/// assert_eq!(mutation_kill_rate_percent(1.0, 0.0), None);
/// ```