To Unit test or not to unit test
So much was and is being written about unit testing. There is without a doubt a pretty solid foundation out there that points in the direction that unit testing might be something we should do as developers to ensure that our code does what it is supposed to do.
Be aware that this post contains strongly held beliefs and opinions of mine, that always have to be taken with caution.
What this post will cover
- Reasons why testing seems like a good idea
- Reasons I heard why others do not want to test their code
- Some ideas to convince others to adopt the idea and spirit of TDD
What this post will not cover
- Unit testing vs. Integration or other kinds of testing
- How you perform unit testing / What is it
Why write unit tests in the first place
There are countless reasons to write unit tests, and in particular write them before you write your production code. All those tend to make the result much better structured than without tests. So this list might not be comprehensive, yet it is what I could come up with at this moment:
- you will need to think first about your code, to write effective unit tests
- you will find sloppy coding mistakes right off the bat
- you have a secure way to refactor, without the feeling something might have gone wrong
- you design your code for extensibility, or else testing is not fun
- you will develop better api’s, because your tests require it to be easy to understand
- you have ad hoc documentation of the api
- you could always loose your production code, as long as you have the test code you are equipped to return to production in no time
- you can find bugs by triangulation
- the intent of your code is much more clear
- you only implement enough to work with the specification, aka tests
- it lets you grow as a developer, because you view coding from different perspectives
- it makes your life so much easier down the road, when the project has grown immensely (refactor, better component design, tests in place)
- in the long run your development speed flattens, but does not invert as much as without tests (speculative)
There might be much, much more but most of the reasons above are good enough to justify tests on their own.
Why would one not do this?
So now I need to ask the question like so many people did before me: Why would someone not want those benefits?
So I can only tell you the reasons I heard from others, because I personally was hooked from the day I encountered this concept (for one reason I had a good teacher, for another reason I have a strong urge to be confident with my work). Even though I made a lot of mistakes, and probably did not really increase the development speed of mine at first. Yet I felt much more confident that my code works as it is supposed to.
And I heard a lot of reasons but really none that could not be debunked with any of those reasons I mentioned above or be an excuse for “I do not want to learn something new”.
So I will list them as “legitimate” reasons and “illegitimate” reasons. (again not comprehensive list)
First the legitmate reasons:
- In a prototype
Yeah you really do not need to write unit tests, if you do prototyping the right way (test a single functionality or feature etc.) and throw it away after you made your point or tested a framework or whatever.
In all other cases and so called “prototyping” were it is integrated in production code immediately after it is finished and reviewed. Even though this should be avoided in the first place, you must still write tests then.
- In an extremely irrelevant subdomain of the application
The question is then, why bother building it yourself and not buying it off the shelf? So not a real reason either (IMHO).
- It is too hard to test with unit tests
Okay what does it mean to hard? I do not know, but calling some unsafe code for example or make some file operation or database calls could count as too hard. Because they are, those should be mocked away and then be tested in integration tests. So they are not to hard to test, they are just not unit testable in the way a unit test is defined as the smallest possible unit to test (class and/or method).
(Proceed with caution: strong and questionable opinions ahead)
Now to the ones I call illegitimate, because they are all some kind of masquerade for “I do not want to _____ more” where blank could either be:
I will not go into detail only list the ones I have heard (I marked the most hilarious parts from my point of view):
- Testing creates too many files, you should rely on KISS (Keep it simple stupid)
- Testing is too complex
- Testing does not find all defects so there is no ROI
- We still have bugs even though we test
- You cannot test everything, so why bother at all?
- Testing is so dogmatic, I want to be a rebel (edited the last part 😉 )
- I do not understand it, and I do not like it
- All the time I change my code I have to change my tests too, I do not see the benefit
You probably have heard some of them, or any other flavors of this. So why so harsh? I do not mean to offend anyone (even though I probably do), yet programming is a team sport and it is much easier when all try to adhere to best practices (they are called so for a reason). Also some of those reasons might stem from insecurity or not understanding what the goal of testing is in the first place.
I do understand that testing is not something you do in your first days as a programmer, because lets face it, it is complex enough as it is and testing has a very steep learning curve. But what I do expect from most other developers, that they are open minded for ways to improve their abilities. I mean that is a big part of the fun of this profession (ok at least for me and some other coders I know).
How can one convince others that testing is useful
Now with this status quo evaluation, how do you get one to do this if they do not want it?
I do not want to convince anyone against their will. If they really do not want to test for whatever funky reason they might have, so be it. On the other hand this will not stop me from testing either.
So the idea is to convince them in a way that they want to learn it intrinsically. This can be done by adhering to their personal idea why it might help them in the future. This idea and the following is from the book how to win friends and influence people (one of the best books out there on helping your career flourish with no regards to the field you are working in btw.), which I recommend anyone and everyone should read at least once in their lifetime, or better yet once each year.
So for example if one wants to work as little as possible (a pretty offensive work ethic from my point of view, but people are different), you could try to explain to them, that it might look like more work now, but it lessens the work in the future with regards to debugging and such.
Or like for me, I have a strong urge to be confident with my work. So before I knew about TDD and unit testing, I used lots and lots of Debug.Assert statements, or threw exceptions wherever something was not compile time safe etc. So for me one could have appealed to my need for safety.
For others it might be to appeal to higher motives, like “do it for the team” or something like that.
But the best way is to be open minded about it, do not force other people to write tests, that probably will not end well. Go and talk with them, not to them. Explain why testing is important and a good idea, listen to their concerns, offer your help and then decide how you could find an agreement.
In the end, not everybody can be convinced, and maybe that is a good thing. Every person has their own reality, and this makes the world (of software development) a good place to be (most of the time 😉 ).
Another view on this
Unit testing might not be the full picture to secure a good design and architecture, heck it might even not ensure that your application does what it is supposed to do. Yet it is a piece of the puzzle and ought not to be ignored.
Essentially for the full picture you should do integration testing in an CI way, do reviews and inspections, pair programming and brainstorming sessions.
But all this needs the mindset of team players and engineers who are hungry and want to learn something new everyday, which I think for one reason or another is not the case with everyone.
We looked at reasons why unit testing might be a good idea and the reasons people think it is not such a good idea after all.
Because I am in the first camp, I then looked at ways how to convince other developers to try unit testing for themselves and what might work towards that goal.
And boi did I rant in this post. 🙂