Code Coverage
Overview
Code Coverage is a measure used in software testing to describe the degree to which the source code of a program is tested by a particular test suite. It helps identify untested parts of a codebase.
Types of Code Coverage
flowchart TD
subgraph DF["Data Flow"]
direction TB
DU["All DU Paths"]
Uses["All Uses"]
Defs["All Defs"]
DU --> Uses --> Defs
end
subgraph CF["Control Flow"]
direction TB
Paths["All Paths"]
Basis["All Basis Paths"]
LCSAJ["All LCSAJ"]
Branches["All Branches"]
Stmts["All Statements"]
Paths --> Basis
Paths --> LCSAJ
Paths --> Branches
Basis --> Branches
LCSAJ --> Branches
Branches --> Stmts
end
subgraph PRED["Predicates"]
direction TB
Comp["All Compound Conditions"]
MCDC["MC/DC"]
Basic["All Basic Conditions"]
Comp --> MCDC --> Basic
MCDC --> Branches
end
Uses --> Branches
style DU fill:#f0f0f0,stroke:#999
style Uses fill:#f0f0f0,stroke:#999
style Defs fill:#f0f0f0,stroke:#999
style Comp fill:#f0f0f0,stroke:#999
style MCDC fill:#f0f0f0,stroke:#999
style Basic fill:#f0f0f0,stroke:#999
Mutation Testing
flowchart TD
subgraph MUT["Mutation Coverage"]
direction TB
Strong["Strong Mutation"]
Firm["Firm Mutation"]
Weak["Weak Mutation"]
Strong --> Firm --> Weak
end
Statement Coverage
Definition
Statement coverage requires every statement (node in the control flow graph) to be executed at least once.
-
Metric:
\[\text{Coverage}_{statement} = \frac{\text{Number of executed statements}}{\text{Total number of statements}}\] -
Pros: Simple to measure.
-
Cons: Weak — it doesn’t consider control flow (e.g., decision paths).
Example
input (A)
x = 0
if A < 5 then
x = 4
end if
y = z / x
Test case: A = 2
- All statements are executed → ✅ 100% statement coverage
- But if
A >= 5,x = 4is skipped, and division by 0 causes a runtime error ❌
CFG for Statement Coverage
graph TD
A1([Start])
A2[x = 0]
A3{A < 5?}
A4[x = 4]
A5[y = z / x]
A6([End])
A1 --> A2 --> A3
A3 -->|True| A4 --> A5
A3 -->|False| A5 --> A6
✅ For A=2: All nodes visited ❌ For A=6: x remains 0 → division by zero not caught with only 100% statement coverage
Discussion
Also known as:
- Line coverage
- C0/C1 coverage
- Basic block coverage (sequence of statements with no branches)
If some statements are never executed, then the verification process may have ignored some required functionality.
Branch Coverage
Definition
Branch coverage requires each possible branch (true/false) of every decision point to be taken at least once.
-
Subsumes: Statement coverage (more thorough)
-
Metric:
\[\text{Coverage}_{branch} = \frac{\text{Number of executed branches}}{\text{Total branches}}\] -
Pros: Catches more faults than statement coverage
-
Cons: May miss faults in compound conditions
Example 1
Same code:
input (A)
x = 0
if A < 5 then
x = 4
end if
y = z / x
Test Suite 1: A = 2
- Covers only the true branch
- ❌ Branch coverage is not 100%
- ❌ Fault not revealed
Test Suite 2: A = 2, A = 6
- Covers both branches of the decision
- ✅ 100% branch coverage
- ✅ Division by zero fault detected (when
A = 6)
CFG for Branch Coverage
graph TD
B1([Start])
B2[x = 0]
B3{A < 5?}
B4[x = 4]
B5[y = z / x]
B6([End])
B1 --> B2 --> B3
B3 -->|True| B4 --> B5 --> B6
B3 -->|False| B5
Both branches (True and False) from the condition are executed in full branch coverage.
Example 2 – Branch Coverage Misses Faults
Requirement:
| A | B | Result |
|---|---|---|
| F | F | 0 |
| F | T | 1 |
| T | F | 2 |
| T | T | 2 |
Buggy implementation:
input (A, B)
Z = 0
if A then
Z = Z + 1
end if
if B then
Z = 2
end if
print(Z)
Test Suite: (A=T, B=T) and (A=F, B=F)
- ✅ 100% branch coverage
- ❌ Bug in
Z = 2overrides previousZ = Z + 1 - ❌ Output wrong for
(A=T, B=F)(should be2, not1)
Discussion
Also known as:
Each decision divides operational scenarios into distinct cases. Good tests must explore all such cases.
All Path Coverage
Definition
All-path coverage requires that every feasible path through a program is executed.
- ✅ Most thorough
-
❌ Impractical for large programs:
- With
ndecisions → up to2^npaths - Infeasible for complex software
- Instead basis path coverage is used
- With
Unfeasible Paths
Some paths can’t be executed due to semantic constraints, even though they appear valid in the CFG.
Example:
flowchart TD
Start((Start))
A{Condition A?}
B[Block S1]
C[Block S2]
D{Condition A again?}
E[Block S3]
F[Block S4]
End((End))
Start --> A
A -->|True| B --> D
A -->|False| C --> D
D -->|True| E --> End
D -->|False| F --> End
style A fill:#ffdddd,stroke:#ff0000
style D fill:#ffdddd,stroke:#ff0000
Here, Condition A is checked twice, making some path combinations logically impossible (e.g., A true first, then false later).
Realizable Complexity (rc)
Reference: Beizer, B. Software Testing Techniques [3]
- Realizable complexity (rc): Max number of distinct, testable paths
- May be less than cyclomatic complexity due to unfeasible paths
- Undecidable in theory: You can’t always determine which paths are testable (linked to the Halting Problem)
Beyond Statement, Branch, and Path
These criteria cover the foundational structural measures. For deeper coverage of specific criteria, see:
- Basis Path Testing — Cyclomatic complexity and independent paths
- Multiple Conditions & MC/DC — Compound predicate coverage for safety-critical systems
- Data Flow Coverage — Definition-Use pairs and variable lifecycle testing
- Mutation Testing — Measuring test effectiveness through fault injection
References
- M. Roper, Software testing / Marc Roper. in The McGraw-Hill international software quality assurance series. London: McGraw, 1994.
- B. Beizer, Software testing techniques. dreamtech Press, 2003.
- J. E. Hopcroft, R. Motwani, and J. D. Ullman, “Introduction to automata theory, languages, and computation,” Acm Sigact News, vol. 32, no. 1, pp. 60–65, 2001.
Disclaimer: AI is used for text polishing and explaining. Authors have verified all facts and claims. In case of an error, feel free to file an issue.