Black Box vs White Box Testing: Two Different Case Sets
Run one feature through both and they produce genuinely different cases. Which set survives a refactor, and which one an auditor can actually read.
Most explanations of black box vs white box testing hand you a taxonomy. One tests without seeing the code, one tests with the code open, and here is a table of advantages. All true, and none of it changes what anybody writes on Monday.
The useful version is a consequence rather than a category. Take one feature, write cases for it both ways, and you get two genuinely different sets. They catch different bugs, they survive different amounts of change, and only one of them is still readable by somebody outside the team eighteen months later. This post runs a single fee calculation through both and shows what each produces.
The two definitions, quickly
Black box testing works from the outside. You know what the feature is supposed to do, and you exercise it through its real interface. You do not look at how it is built.
White box testing works from the inside. You read the implementation and design cases to exercise its structure: the branches, the loops, the error paths, the conditions.
That is the whole distinction. Everything interesting follows from it.
The same feature, written both ways
A payments service charges a fee that varies by account tier. Personal accounts pay 2.4 percent, business accounts 1.4 percent, enterprise 1.1 percent. There is a minimum fee of 0.30 and a cap of 50.00. Fees are rounded to two decimal places.
Black box cases come from that description alone:
- A personal account sending 100.00 is charged 2.40
- A business account sending 100.00 is charged 1.40
- An enterprise account sending 100.00 is charged 1.10
- A payment small enough that the percentage falls below 0.30 is charged 0.30
- A payment large enough that the percentage exceeds 50.00 is charged 50.00
- A payment exactly at the point where the percentage equals the minimum is charged 0.30
- A payment exactly at the cap boundary is charged 50.00
Seven cases, derived from the rules a customer was promised.
White box cases come from reading the code, and they look different:
- The branch that selects the tier is exercised for all three tiers plus the default
- The default branch, which nobody documented, returns 2.4 percent for an unknown tier
- The rounding helper is called once, not twice, because calling it twice compounds
- The minimum check runs before the cap check, so a value that triggers both returns 0.30
- The early return when the amount is zero skips the tier lookup entirely
- The cached tier lookup is invalidated when an account is upgraded mid-session
Six cases, and only two of them overlap with the black box set.
Look at the fourth white box case. The order of the minimum and cap checks is not in any specification. It is a fact about the implementation, and it is exactly the kind of thing that changes silently in a refactor. A black box tester would never think to write it, because from outside there is no reason to believe the order matters.
Now look at the second white box case. There is an undocumented default. Somebody reading the code found behaviour that no requirement describes. That is a finding, and it is the strongest argument for white box work: it is the only technique that can tell you the code does something nobody asked for.
Which set survives a refactor
Here is the practical difference that matters most for a suite you keep for years.
A developer replaces the fee calculator. Same rules, cleaner implementation, the minimum and cap checks now happen in one pass instead of two.
Every black box case still passes, and still means the same thing. The promises did not change, so the cases that verify the promises did not need to.
Four of the six white box cases are now meaningless. The branch they described no longer exists. They will either fail, and somebody will spend a morning discovering the failure is about a structure that has been deleted, or worse, they will pass for the wrong reason.
That asymmetry compounds. A suite that is mostly white box needs rewriting every time the code is reorganised, which is why those suites quietly rot. A suite that is mostly black box keeps working, because it is anchored to something more stable than the implementation.
Which one somebody outside the team can read
The other asymmetry is about audience.
A black box case can be read by a product manager, a support engineer, a customer, or an auditor. It describes behaviour in terms of inputs and outcomes, which is the language everybody shares.
A white box case usually cannot. "The default branch returns 2.4 percent for an unknown tier" means nothing to somebody who has not read the function, and it does not obviously map to any requirement.
That matters when the test record has to do a job outside engineering. When somebody asks what evidence you have that the fee rules work as documented, black box cases answer the question directly. Each one names a rule and shows it was checked. This is the same reason an approval log next to the case is worth keeping: the record has to be legible to the person asking.
None of that makes white box cases less valuable. It makes them differently valuable. They are engineering artefacts, and they should be judged as engineering artefacts rather than as evidence.
What each one misses
Being honest about the gaps is the fastest way to decide how much of each you need.
Black box testing misses:
- Undocumented behaviour, because you are testing the specification rather than the code
- Dead code and unreachable branches
- Paths that only trigger under internal conditions you cannot set from outside
- The reason for a failure, since you see the wrong output but not where it came from
White box testing misses:
- Missing features, because there is no code to read for something nobody built
- Whether the requirement was right in the first place
- Anything about how the parts behave once assembled
- Usability of any kind
That first white box gap is the one people underrate. If a requirement was never implemented, no amount of reading the implementation will reveal it. Only a case derived from the promise will fail.
Choosing per case, not per project
The framing that helps is not "which approach does our team use". It is "which one does this particular risk need".
A practical rule that holds up:
- Start from the promises. Write the black box cases first, because they are the ones that must exist regardless.
- Read the code afterwards, and write a white box case anywhere you find behaviour the promises do not cover.
- When a white box case describes structure rather than behaviour, keep it close to the code, not in the long term suite.
- When you find undocumented behaviour, the output is not only a test. It is a question for whoever owns the requirement.
That last point is where this stops being a testing technique and starts being useful. The most valuable thing white box work produces is usually not a case. It is a conversation about a default nobody chose.
The wider map of testing types covers where these sit relative to the layers of the suite. Keeping both sets discoverable, with the reason each was written, is ordinary test case management work.
Questions people ask
What is the main difference between black box and white box testing?
Whether the person writing the case has read the implementation. Black box cases are derived from what the feature is supposed to do. White box cases are derived from how it was built, including branches and error paths that no requirement mentions.
Which is better, black box or white box testing?
Neither, and the question hides the useful one. Black box cases are more durable and more readable. White box cases find undocumented behaviour and dead paths. Most teams need mostly the first kind in the long term suite, and the second kind close to the code.
Is unit testing white box testing?
Usually, yes. Unit tests are written by someone reading the implementation and are designed around its structure, which is the definition. That is also why unit suites need rewriting whenever the code is reorganised.
Do testers need to read code for black box testing?
Not for the cases themselves. Reading the code often makes a tester better at guessing where to probe, which blurs into gray box work. The distinction is about what the case is derived from, not about what the tester happens to know.
Which type of testing should we document for an audit?
Black box cases map cleanly onto requirements, so they are the set that answers questions about whether documented behaviour was verified. What any specific auditor accepts depends on their framework and scope, so confirm the expectation rather than assuming.
Try Tesbo, or get the next useful idea
Start building your testing workflow now, or get one practical email a month.
Get startedOne email a month
What we shipped, what we learned, and the occasional infographic worth pinning. Unsubscribe in one click.
