Black and White
Black box, white box. Does our choice of perspective matter?
We’ve landed this function declaration:
We’re told that it adds two integer numbers. How should we test it?
Let’s see, we can check that sending 2 and 3 returns 5. We can also send 3 and 4, and expect 7.
Then, we have these “edge” cases, like adding two big integers to see their behavior (if it is an overflow). There’s also negative numbers, and combinations.
All right. We’ve got an idea for some tests. Let’s say around ten.
Now, Let’s look at the code underneath.
We know a bit more. Do we still plan to write the same number of tests?
We now know, that what we’re really testing is the behavior of the “+” operator. In fact, we now know that our add function works exactly like “+”. Overflows included.
So, do we really need to even test “+”? Has it ever failed us?
Well, not in recent history. But what about future-proofing? If someone changes the implementation somewhere in the future, our add function will no longer, well, function as expected. Like replace “+” with a complete new math library implementation.
Maybe we should write all these tests, just to make sure.
What should we do?
Things change when we look into the abyss, eh?
When we write automated tests (not just unit tests), we do some risk analysis calculations. We invest in tests, in order to get some benefit (early warning). We want the benefit to outweigh the cost. If we don’t see that happening, we won’t write the tests.
Our analysis changes when we have more information. Including how the code is implemented. Or how the system is designed. Or what it uses as third-party. Or even who writes the code. We understand more about the risks, and we may change our decisions.
Knowing more makes for better decision. We can blindly cover our black box, and we can use less tests if we know what’s it made of.
What do I say about this case?
If I knew this code (the white box scenario), I wouldn’t bother with a test. Maybe one. But definitely no future-proofing. I assume (and I maybe wrong) that if someone changes the implementation, they would also write tests for it.
If I was writing it in TDD, I would have a single simple test (like 2 and 3 returning 5), then move to other implementations.
The risk doesn’t warrant that kind of effort.
Want to learn how to unit test? Know but want to be even better? Want to hear more unpopular opinions on testing?
Check out my unit testing and TDD workshop.