Unit Tests: a software tester’s perspective
I’d been curious about unit testing (UT) for a while. And with a little practice, I managed to apply a few of the UT concepts to my personal projects.
Below is a summary of what I understand so far on UT:
In unit testing, one has to understand what’s going on under the hood to thoroughly perform it. Most code nowadays can be broken down into unit modules (lets call it blocks). The logic of the software design is such that some of these blocks interact with each other by sending and receiving data from and to each other, while other blocks send and receive data to the public (i.e they receive input from the user). At a risk of sounding like a real nerd (which I kinda am), unit tests are usually written for the individual unit blocks that are not exposed to the public. Make sense? Of course it does! I knew you would get it.
With that being said, it is obvious that for a tester to perform unit tests, the tester would either have to pair with a developer to determine the code structure/design or at least understand intimately the ‘logic’ of the code. Perhaps, this is why it’s been said that unit testing should be left to the developers. However, true SDETs (software development engineers in test), should understand what unit tests are all about.
Unit tests are functional tests. Although functional tests generally are applied to the functional behaviour of the system that can be manipulated by the consumer (exposed to the public). Unit tests in particular and as a subset of functional tests are applied specifically to the internal isolated methods.
Let’s look at an example. Say that you are developing a code that simulates a ‘vending machine’. Let’s assume the following (hopefully the names are self explanatory) methods are directly interacting with the public:
- inputMoney()
- selectProductCode()
- stockProduct()
- dispenseProduct()
Internal methods not particularly exposed to the public could be
- checkForAvailableProductSelected()
- isBinEmpty()
These internal methods are ideal candidates for unit tests.
What is the Approach to Unit Testing?
It can be quite exhausting coming up with the right inputs to plug into these methods to expect wanted and unwanted outputs. Do you deal with edge cases only? What combination of inputs should you use? What about unhappy paths?
I came across a guide from teamtreehouse.com that can be used for general coverage with unit tests. This guide can be expanded upon depending on how detailed you intend your tests to be. It’s called CORRECT:
Conform: What happens when the unit receives data input that does not conform to the format needed.
Order: Is the data data received in the expected order? What happens when it is in an unexpected order
Range: What happens when we input data over the min or max value allowed?
Reference: does this unit reference code from another unit? Is that other unit tested?
Existence: Can inputs be null? If so, what happens?
Cardinality: What happens with a zero, single values and multiple values for inputs?
Time: Take time into account. Applications sometimes require things to happen in a certain order, at specific times. What happens then they do not?
Unit tests are extremely advantageous when performed efficiently because logical flaws in the code can be detected very early in the development process.
That’s all for now folks.
Nathan Maduakor is a software developer in test for The Telegraph. Follow him on nathandaily.com or @itsnathandaily.