First bug ever found in software development. More info at the wikipedia
This article is targeted at my friends, the friendly developers, I´m going to persuade them to join the unit tests army revolution!
So be sure to read the entire article and invite me a coffee if you learned something valuable.
A software bug is an error, flaw, failure or fault in a computer program or system that causes it to produce an incorrect or unexpected result, or to behave in unintended ways. Wikipedia
Nobody wants to work more than enough and a developer just wants to write the bare minimum code to implement the assigned tasks so, at the wages day, he gets a salary.
Who wants to spend more time, even full working days, coding tests? and what for? Why on earth are these QA-nobody-knows-what-they-do workmates hunting me down urging me to code some useless tests?
Developers are smart people so they always code without errors, aren’t they?
The truth is that even the best of the best developers has a bad day, hasn´t slept well the before night, has had an argument with his/her friends…Nobody is at 100% all the working day, every week, every month, every year…and so everybody makes mistakes (even the incredible QA members!).
As if that weren’t enough, there are a lot more reasons explaining why the software we code, even though we put a lot of care, love and sweat on it, has bugs:
– Failures or problems in communication. In software development there is always the chance of miscommunication, lack of communication or erroneous communication.
Ex. Tasks where the requirements are vague or incomplete, does it sound familiar? The «left hand» and the «right hand» don’t always stay tuned. You saw this coming, didn’t you?
– Time. Anyone heard about really crazy release schedules? Not enough resources? Project deadlines chosen by the roll of a dice? We are always in a hurry, there is no time to think, time to plan, time to design, time to understand the complexity of the task at hand. This is the life we live in and it´s very hard to keep calm, stay focus and allocate the required time to the tasks we have to code.
– Tasks complexity. Software gets more and more complex every day. Every project tends to be more difficult than the last one and this is NOT a bad thing! A developer always needs new challenges, new tasks he hasn’t done before so he doesn’t get bored. But as each new task gets more and more complex the developers are going to need more time to code research and develop it so they can find reliable solutions.
Time and complexity are intimately related. The inherent complexity of the tasks could be somehow avoided if we were assigned more time to the design and for implementation phases, and the tasks would be finished in less time if they weren’t so complex.
– Last minute changes. We are living in an agile world and so we shouldn’t be afraid of constant changes, but getting used to it is not for the faintness hearts. Changes made to the requirements one or two days before the project release date are very difficult to accept without yelling at the ancestors of your beloved bosses. And these last minute changes are even harder to code without breaking anything. It’s for sure a recipe to destruction, let the door open for the bugs to come!
– Last but not least, QA team members need a reason to get paid ;). This is really not a reason but as a QA engineer I have to sell myself out!
So how do we manage this ugly army of bugs that like to appear at the worst moments (Datio Demo days, Head of Data presentations, holidays and the like)?
Here are some ideas that everyone of us has been thinking of every time a situation like that occurs:
– We could try to ignore them, forget about them, trying to swept it under the carpet and so, if we are lucky enough, they won’t get the necessary attention and if so, nobody needs to solve them out! Life goes on…isn’t it? Ignorance is bliss.
– We could try to put the blame on another team, preferably from another office, even another company on an abroad African country. A team we don’t know anything about (did you say IaaS?) and therefore we don´t mind if they take the blame. Even we could gain enough time to debug the fix and find a way to show ourselves like the company saviors.
– We could create an easy «work around» procedure avoiding the bug coming out from the dark side…If we have another way to get the same result, why on earth do you want to go that way that only leads to the bugs dark side? Who cares if the workaround implies some madness procedure (like a barefoot trip through Canada)
There are for sure many, many more ways to deal with the bugs. For sure you can teach me one or two, but only one nice solution: fix the bug.
[Footnote: Contact me to tell me about your incredible intelligent ways of avoiding fixing the bugs]
So, once more, the developer needs to seat in front of his computer leaving unfinished other important tasks (like table football league matches, Nerf competitions…just a rest in the terrace?) and start looking after the nasty bug. And, as you know, this is not an easy and rewarding task!. You made your bed, now you have to lie in it.
An immaterial structure built on a broad supporting base and narrowing gradually to an apex. Merriam-Webster
Why don´t we make a change? Is there any other way to do this? Some wizardry magical potion to keep the bugs out of your code? Or do we need to hit the same stone again and again? Where there’s a will, there’s a way…
YES, there is, and the pyramids can help you a lot! You’ve read it right…pyramids
Almost every civilization on earth has built some kind of pyramids. The Mesopotamians built the earliest pyramidal structures, called ziggurats. The most famous pyramids are the Egyptian. The Igbo culture (Nigeria) built the Nsude Pyramids. Even in Spain (Tenerife) we have the Pyramids of Güímar! So…I see pyramids everywhere, why not on software development?
There is one great testing pyramid that try to visualize the different levels of testing types any application should have:
As you can see, at the very bottom of this pyramid resides the dreaded and long forgotten unit tests. And, look at it closely…the space takes the unit tests portion in the pyramid is the greatest one! No doubt!
There is a lot of literature out there over the Internet explaining the pyramid, the levels and the importance of each one, but I´m going to give you only one reason:
Fail, fail fast and as soon as you can!
If your code is going to be the tourist destination of some band of criminal bugs, the best thing to do is to clean it up as soon as you can! Trust me, it will give you some extra rest and sleeping nights 🙂
When I say «As soon as you can» I refer to the base of the pyramid, the unit tests.
Unit tests finds problems early in the development cycle and are cheaper to fix. This means that you could fix them easily and fast, even before anybody other than you finds them.
From a experienced tester point of view, my advice is to code as many unit tests as you need and your application will have a safe net that will reward you in many ways.
Yeah, I’m hearing you complaining about my advice. As many unit test as you need? How many tests to code? I don´t want to code so many tests…
Well, this is one of the key questions. Which is the magic number? How many unit tests should I code? and there is one easy solution: you can count on your QA mates. They will be very helpful trying to give some help.
So let´s go to the shopping lists.
3. Shopping lists
Shopping list is one of the 30000 most commonly used words in the Collins dictionary. Collins dictionary….did you expect anything else?
Oh my! Do we really we need a shopping list? Pencil and paper? Going to Mercadona to buy the leaf? Are you serious?
Yes I think we need to write the unit test cases down. Not the unit test code but a description of each unit test you need for a method, function, class…
This will help you later to prioritize them so the most important ones are coded first. The list order will be based on the priorities of the user requirements.
Think first, and then think again. Last but not least, think…always think. You need to test the user requirements first! You could write a zillion test for an application but always start with the ones that check your user requirements and do it in the predefined order.
Create a user requirements list and order them by priorities. This list should be ordered by the user priorities. At the bottom of the list add the checks that, even when they are not specified on the user requirements, would be nice to have to ensure there is no room left for bugs.
Never ever look after achieving some generic goals, per example a minimum number of unit tests to pass a static code analysis tool check. There is an insane trend in the tech companies that setup this kind of tools to check every application with the same requirement levels.
Every application has its own requirements, characteristics, business priorities, etc…and so, every application should be checked as one unique specie of its own! with its own quality gates and peculiarities.
Go out your cubicle and kidnap a QA team member and ask him kindly for help, teach him how your application works and the business functionality to fulfill. Together analyze the priorities list you created and try to add/delete/modify/order it, if needed.
Finally show him/her gratitude for helping you and start coding the unit tests following the priorities list.
It is very possible that the number of unit tests created just to check the user requirements are less than the required number of test to pass some established «quality level». This is not wrong. If there is time, you should continue coding the unit tests corresponding to the rest of the created list. Maybe then the «magic number» is finally reached…or maybe not. Again, this is not wrong! The list has been agreed with a QA mate so it is complete and checks all the functionality you’ve coded.
Any QA workmate should come helping with a list of things that should be tested:
– What happens when the method is taking too long to respond? Why don´t we check the response time?
– What happens if the service is just restarted when the request is sent?
– Why don´t we have any negative test cases?
– What happens if we make two or more calls at the same time?
– What happens if the input does not have the expected format?
– What happens if the input tries to crash the method?
And many more cases that should be tested. Many of the tests won’t be unit test type but you should take note and write them down.
Hey! I almost forgot the most important point! Don’t wait to start coding the unit tests till all your requirements are coded! Start coding unit tests AS SOON AS possible. When implementing a feature, code together the unit tests required to check the feature.
EVEN better develop following some TDD (Test-driven development) method.
In a few words, code the test first and then the code to pass them. This is a nice approach to software development that won’t let you forget about coding the unit tests.
And there is another important thing to do: don’t forget to check in the code (code + tests) in the development pipeline when the feature and the unit tests are completed. You heard about C.I. and C.D., haven’t you?
When the unit tests are coded, they help in many ways:
– Bug fixes won’t have side-effects and you will sleep with a clear conscience 🙂
– The developers will be less afraid of changing old code without breaking any existing feature.
– New features added to the application don’t break the existing ones. The world is constantly changing and your application will change too for sure! As the agile people like to say: embrace the change! (or was it: join the post-it dark side?)
– As an application evolves, refactoring is needed to maintain the code quality. A good set of unit tests are a real life insurance.
– The dreaded quick bug fixing! From time to time a problem arise in production systems and it will be necessary to get it fixed fix as soon as possible. Have you been in this situation before?: right in your seat in front of your laptop, trying to code a fix as fast as you can with many «important» people just sitting beside you waiting for you to finish it? The kind of people that think that breathing over your shoulder will help speeding things up? For sure you will have a fix in no-time but…what about the side-effects? Does anybody care about the side-effects? This fix should be in QA hands to test it thoroughly, isn’t it?
But reality is always going in the wrong direction. Your lovingly boss suggests you to deploy the fix to a production environment getting rid of the QA team.
At least you will have an Ace up the sleeve. While building the fix, your great and marvelous set of unit tests will come to the rescue! It is not the way it should be, but at least you will have a minimum confidence in not breaking anything else or introducing a new problem to the mix!
– It helps improving the agile term «Truck Factor». With a good set of unit tests, you as a developer in a agile team should have enough confidence in changing any piece of code written by a team mate even if you don’t know the particular details about it.
[Footnote] Truck Factor: “The number of people on your team who have to be hit with a truck before the project is in serious trouble”
4. The Ugly
With great power comes great responsibility. Spider-Man
Yeah, I’ve got bad news too :(…The great unit tests have their dark side too…Maintenance!
Don´t forget of the maintenance work needed in the future. This work is very important! In each sprint the application is going to change, adding, deleting or modifying functionality and so the unit tests should be changed in accordantly.
This maintenance work is going to be boring. You will have to analyze all your unit tests looking for:
– The ones that need to be taken out of the suit because they are not needed anymore. As the functionality of the application changes, some unit test will became useless, even returning «false positives». This tests should be taken out of your suit.
– The ones that need to be updated as the requirements have been modified. This should be an easy task, boring but easy 😉
– The new ones needed. New functionality implies new unit tests but also modified requirements might imply new tests too.
We could even suffer a case of the Pesticide Paradox (Boris Beizer): «With the Course of Time Test Suites Wear Out».
Writing unit tests is an extra effort if compared to not writing tests at all 😉 Even more, your unit tests will need to be maintained!. This extra time should always be included in the planning sessions! Don´t forget about it, go to the tattoo shop and engrave it in your left arm right under your «I love my mum!» tattoo.
The time taken to complete a feature will increase including the needed time to code and maintain the unit tests but never forget the benefits will pay off greatly!
Unit tests are the easiest tests to code and, in return, are the most rewarding ones. A unit test just verify a minimum piece of code (ex. just one method or methods of a class.) and so, they are easy to code and fast, very fast to run.
Remember…easy to code! They are just checks, no high-end develop techniques are needed (don’t think about monads, interfaces, development patterns…).
This type of tests don’t have relation with other applications or external systems so you are not going to need a production-like environment to run the tests.
Forget about end-to-end checks and integration checks. Focus only on your app and run the tests on a local minimal environment just by running you app.
The communications with other apps should be mocked as easily as possible.
Writing good unit tests takes time, effort and skills. Time? nobody has enough time so my only advice is to plan your work carefully. Effort? Well, I think everybody has the capacity to make everything they want to, independent (independently) of the required effort. You are only limited by your own attitude. The right attitude can move mountains. Skills? you as a great big data developer have more than enough skills, don’t you?.
So far so good but don’t forget that coding excellent suites of unit tests doesn’t get rid of the need for a manual tester! Unit testing it’s not a silver bullet! Trusting blindly in unit testing is, again, a recipe for destruction and chaos >:)
Never ever an automatic process will discover as many bugs as a human can do. If your application is also being tested by a great and experienced friendly tester this would boost the quality to levels behind your wildest imagination! To the infinity and beyond (Buzz)
There are, and there always be, bugs in production code. Some of them we will never know about but some another will show at any moment breaking your Zen and peace. Even when your unit tests are great! You will have to think about getting integration and acceptance tests and also an smart QA doing exploratory testing.
Those nasty bugs are going to be there waiting under the bed! But you will be ready to fight them back and, even better, many of them will be avoided in the first place.
May the unit test be with you!