On The Edge
A lot of people use the term “Edge Case”. I find it offensive.
Ok, not really, but there’s a misuse of the term. While we’re at it, let’s throw in negative cases, happy and unhappy paths, etc.
We tie in “cases”, which are behaviors, together with code paths. It’s a mapping mechanism. When we’re “testing an edge case”, we’re saying there’s a test going through that “other” code path.
What is an edge case, really?
Maybe it’s the case that the developer didn’t think through. Which is to say, there’s a risk here, and therefore we need to test more, better and deeper. When we’re doing black-box testing, we’re mapping risk to behavior, and we assign high risk to our perception of developers, our history with them, collective trauma and prejudice. We can also define the “edge” in probability terms: Most time one piece of code will execute, but sometimes, another will.
But then, if we look at the code, we’ll probably see the issues and behaviors. The edges are now longer there, because we mapped the risks to code. And code doesn’t have edges.
Let’s take a calculator, for example (of course). Adding two numbers is the “regular” case, the “happy path”. Adding two very big numbers (that may get us an overflow error) is considered an edge case. What makes the two cases different? Hmm. An overflow exception is an “exception”. And therefore… hmm, what then?
Expect the unexpected
When we’re talking behavior, there are only two types: Expected and unexpected. For the expected, we have requirements, and we address it in code. If we expect an error, our code can throw an exception, but it’s still expected behavior. We can decide that throwing the exception is not the behavior we expect, and change the code to fit the defined behavior.
For unexpected behavior, there is no requirement. We can explore it, and if there’s a bug, we might suspect “unhandled” behavior. We can map the behavior to the code, and when looking at it, call it an “edge”. But now it’s become existing behavior. If we don’t like it, we’ll change it.
Code doesn’t have edges
It doesn’t matter – if there’s code for that, there’s no “edge”. We’ve already done the analysis process. Neither is the case “positive” or “negative”. Even if our perception that a “positive” behavior will happen a lot more than a “negative” one. Again, both are expected and supported, and should be tested, in the same rigor.
By assigning different names, we send a signal: This code should be tested more (or less) than the other one. But all code paths are equal. We expect and demand the same quality all around.
We can prioritize effort to expected behaviors. There are important behaviors we want to make sure work. There are less important behaviors which still needs to work, and then there’s untested code. We can decide where to put more effort and where less.
But using terms like edges, negative and others are not helpful in this prioritization. They can even be confusing.
So, stop using these terms. Talk about defined behaviors and expected results. Ask if there’s code supporting those behaviors. Talk about what is more important to test more thoroughly.
And treat all code as positive code. Glass half-full kinda stuff.
Want to know more how I treat code? Check out the Clean Code workshop.