Unit testing can often be a cumbersome practice to introduce into any development team. Many of the converts I’ve introduced to unit testing (myself included) have all despised the practice in the beginning often saying that its takes twice the amount of time.
The art of testing is often an after thought where development is concerned making it hard for developers to get into the mind shift of having to write tests first before they code. It’s my hope that this article will give some more incentive for making the leap.
It has long been known that unit tests are a great way to stick it to Murphy’s Law by covering your code with some fancy footwork and assertions. Fantastic as that may be, we would like to believe that the merits of Unit Testing extend far beyond Regression Testing or “Knowing When I Broke It”. We’ve often found our tests rarely fail as a result of defective code, our most common failures occur when our business requirements changes.
This however comes with the territory as you will need to maintain your test coverage with your code bases, i.e as the Business requirements change the corresponding test will need to reflect the new requirements. So without further ado, here is why unit testing is awesome.
Fishing For Business Requirements
We do a great deal of planning before starting any project, in which we write elaborate user stories outlining the goals, inputs and outcomes of our various business requirements. Unfortunately as awesome as we are, we do tend to miss things… Enter unit tests. I have found that unit testing is a great way to fish for those covert business requirements that often go unnoticed during planning sessions.
You might have a user story that goes something like:
In order to see what I am doing,
As a person in a room,
I should be able to turn on the light,
Given I am in the room,
And Flick the switch,
Then I should be able to see what I’m doing.
As can be seen from this pseudo story, there is a host of business logic between ‘The person flicking the switch’ and ‘Then I should be able to see what I’m doing’. As you find these requirements you will likely need to modify your specifications to reflect the new business logic. Additionally this process of fishing for requirements also sharpens the mind, and helps one to better anticipate these types of things in the future, so one could argue that testing is the path to enlightenment.
It is often forgotten that it is not so much about writing tests, as it is about writing them “correctly”. On the journey of unit testing, you quickly realize that in order to write tests for your code, you need to write code that can be tested. This is where single responsibilities become incredibly important. The moment you find yourself writing tests that make multiple assertions for relatively unrelated things, chances are that you doing something wrong.
Here is an example:
You could have a method call send_correspondence which sends out an email and an SMS, you might want to write one test that calls this method followed by an assertion to ensure that both the SMS and email have been sent. This would be incorrect as you need 3 independent tests: one for sending mail, a second for sending an SMS and 3rd that passes if the 1st and 2nd method is successful.
You could even go as far as to mock/stub out 1st and 2nd method in the 3rd test to cater for the various responses. Not only does unit testing make sure you are not breaking your code, it also forces you to write code of a higher standard.
The concept of single responsibility can even be taken a level higher to the Entities and Models. By sticking to single context specific assertions you will find that your conscious quickly gets the better of you when you try to dissolve the boundaries between Domains/Models. Your test cases should only assert for things that are relevant to the immediate business goal. Once again writing unit tests will ultimately result in your having to segregate your code/business logic and tests into their respective domains.
It would be extremely ill advised to just start writing tests or even code without any predetermined direction. If you opt for this route you will find yourself wrapped in spaghetti test before you can hit ctrl+z. For this reason it his highly recommended that you employ some kind planning through specification and user stories before whacking that keyboard. Not only will this help you write relevant and effective tests but it will also improve your development processes as whole.
There are no adverse effects of testing, with the exception of the slight overhead that testing might add to your process which in my opinion is a small price to pay for the added efficiency and peace of mind. That said, make no mistake, getting any form of testing up and running is no small feat and no small amount of work. A mistake that I have often made is thinking that it could be run on its own, to make a success of it you will want to implement as much of the supporting infrastructure from the word go to ensure a smooth transition. This includes everything from choosing effective methodologies, workflows, release strategies, analysis, design patterns, frameworks and platforms.
In conclusion, Unit Testing allows for far more than just maintaining a stable code base. It promotes a healthy development culture by encouraging the use of best practices. When applied correctly it is guaranteed that you will see tremendous improvement in your team and business as a whole. So I leave you with this….
In order to produce exceptional systems,
As a developer,
I should start writing some tests.