Skip to content

Commit ce97417

Browse files
committed
added post
1 parent fff0fbc commit ce97417

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

2.84 MB
Loading
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: "Why 100% Test Coverage Isn't Enough"
3+
summary: "The 100% Code Coverage Fallacy"
4+
date: 2026-04-07
5+
tags:
6+
- SoftwareEngineering
7+
cover:
8+
image: "bad-release"
9+
alt: "Bad release"
10+
---
11+
12+
## Oops, I Broke the Release 😅
13+
14+
It's the notification that every developer dreads - A bug report landing soon after a fresh release.
15+
16+
While implementing a feature enhancement, I accidentally introduced a critical regression that impacted new service onboarding.
17+
Although existing services continued to run smoothly, a bug in the configuration flow prevented new services from completing the process.
18+
19+
## The Aftermath
20+
21+
The issue was first reported by a single user, but the response that followed was heartening.
22+
Within a few hours, several others who encountered the same problem jumped in to help.
23+
Instead of just vague "it doesn't work" comments, the community provided me with a wealth of valuable troubleshooting data such as:
24+
- Environment and configuration details
25+
- Screenshots
26+
- Error messages and stack traces
27+
- Reproduction steps
28+
29+
This collective effort enabled me to quickly pinpoint the root cause far quicker than I could have on my own.
30+
While I began working on a fix, affected users were advised to roll back to the last stable version.
31+
This also served as a reminder of the importance of having reliable backups and having a well-documented rollback process.
32+
33+
## The "Naughty" Parentheses
34+
35+
Fun-fact: The culprit was a sneaky pair of misplaced parentheses `()`.
36+
37+
In Python, parentheses are overloaded.
38+
They are used for explicitly defining the **order of operations** (similar to Math where expressions within parentheses are evaluated first) and also for defining **tuples** (immutable collections).
39+
There was a set of misplaced parentheses which unintentionally transformed my logic into a tuple.
40+
41+
Since the code was still syntactically valid, this bug was incredibly easy to overlook and slipped through the code review.
42+
43+
## The Post-Mortem: The 100% Code Coverage Fallacy
44+
45+
Part of the standard code review process was to verify that all code changes are covered by tests and a passing test suite.
46+
So, how did the bug slip through tests with 100% code coverage?
47+
48+
**The Mock trap.**
49+
50+
The tests relied heavily on mocks for API requests.
51+
The mocks didn't care whether the input was a single value or a tuple; it was programmed to return a success response.
52+
53+
The crucial piece was missing assertions for inputs.
54+
If I had used `mock.assert_called_with(expected_input)`, the test would have failed and caught the issue before it made it to release.
55+
56+
## Key Takeaways
57+
58+
While code coverage is an important metric in testing, here are some limitations that let bugs slip through.
59+
60+
**The Assertion Gap.**
61+
We often obsess over the *output* but neglect the *input*.
62+
This case was a prime example: the code ran, but because I didn't verify the specific arguments passed to the mock via `mock.assert_called_with()`, the logic failed silently.
63+
64+
**Avoid shallow assertions.**
65+
Checking just the HTTP status code is not enough.
66+
You must verify the response headers and body to ensure the logic is working as intended.
67+
68+
**Missing logic.**
69+
Code coverage only measures code that exists.
70+
It has no way of flagging the edge cases or validation steps you *forgot* to implement.
71+
72+
---
73+
74+
PS: I’m incredibly grateful for a community that brings data instead of drama to a bug report.
75+
The fix is out now, and we’re back on track now, with better tests and stricter assertions.

0 commit comments

Comments
 (0)