January 3, 2015
The Software We Create Must Meaningfully Handle All The Inputs It AllowsAnother quick brain-dump of ideas from the new Advanced Unit Testing training workshop...
A fundamental principle of software reliability is that the software we create must meaningfully handle all the inputs we allow.
Case in point, the sign-up page of a social network I worked on many moons ago. The boss wanted us to collect the user's email address - quite naturally, since the membership functions wouldn't work without one.
It's "just a simple text field" was the thinking. So imagine her surprise when we identified a bunch of different test cases relating to that one "simple text field".
If it's left empty, for example - which it could be - then that's not a valid email address. If it doesn't follow the syntax of a valid email address - and there are several rules to obey here - then, well, it's not a valid email address. If the email address doesn't exist (perhaps because they typed it in wrong), then - valid syntax or not - it's of no use to us. If the email address does exist, but it's not the user's email address, then ditto. And finally, of course, we might already have someone signed up with that email address.
The boss threw her hands up in the air and proclaimed "you're overcomplicating it!"
But, no, we weren't. We were just identifying the consequences of that "simple text box" on the sign-up page.
Had we left it as "enter what you like, we won't check", then our user database would have been riddled with invalid or blank email addresses, and a whole bunch of functionality we had planned simply wouldn't have worked.
Attempting to write software for a social network where some users don't have email addresses would make the whole thing more complicated. Better to simplify core application logic by restricting user input to that which we can meaningfully handle.
From a unit testing perspective, our main concern here is pre-conditions. If we have functions that only work under certain circumstances - e.g., only if the user has a valid email address - then we must design our code in such a way that we can either guarantee that is always true when that function is invoked, or that checks and handles meaningfully the possibility that it isn't true.
Either way, the behaviour must be complete - that is to say, all allowable inputs are accounted for in our design.
I favour the typically simpler approach of restricting inputs to the more demanding approach of handling a wider set of possible inputs.
In this approach, we need to be especially aware of the boundaries to our software, across which inputs flow.
Posted 3 years, 8 months ago on January 3, 2015