Always Test Your Code

23 Jun

How many times have you heard this phrase? How many articles did you read preaching this to you? Then why would people keep talking about this? Well, I guess people are bad at following this advice. I guess people are lazy amateurs, who can’t be bothered to do one thing right, right? Well I don’t know about that. I still hope people are good, you know… professional, smart, nice. Perhaps it’s something else. Perhaps it’s not about how lazy people are, but how hard it actually is. And it is hard. I know, because I myself am failing to test my code. But why is it hard?

Well, after a few years as a software developer, I have a hypothesis. I think, the problem is, that the people focus on the wrong word in „Always Test Your Code“. How about you? Did you focus on the first word? Is „Always“ the most important part of the sentence for you?

Don’t worry, it doesn’t really matter. Just know, that the emphasys should be on „Your“.

Of course this happens often with the written word. After all, not everything is captured when a quote is written down. And if this was somebody’s quote, there’s no guarantee, she had put the emphasis there. But here’s the thing: do you know how much easier it is, if you’re testing only your own code? It’s amazing! But why is it so easy? Well, let’s look into it further.

Let’s imagine you have a test suite, which runs the application and clicks different parts of the UI, after which checks for the changes in the UI. This is a pretty standard end-to-end test. It is very much needed, but extremely heavy. I’m sure you understand why. Since your application was pretty simple in the beginning, this inherent load of the end-to-end tests was not really anticipated, and the test suite grew to the point where you and your team-mates wait for a few hours for the tests to execute, before merging the new piece of code you have to the trunk. The effect is that the test-suite can be executed only a few times per day, if you’re lucky, and the development of new features looks more like test maintenance, than anything else. Furthermore, a bunch of tests are always acting like a Christmas tree and fail only when you don’t look at them. So you don’t pay a lot of attention to them. Meaning there are quite some complaints from the users, that the thing which is tested exactly by this Christmas tree lights-chain is not working.

This is already unbearable, so everyone is wondering „Why are we doing this?“ And usually the management says, „Well, it’s historical reasons“ (I hate this phrase). Sooner or later the management is on the same page and they decide to spend some time for dealing with this burden once and for all.

This is the time when everything gets revealed. It turns out, that the project grew so much, that from the 3 full-stack developers in one team, that started working on it, the company grew to 150 developers in different teams, responsible for different subprojects, each of which provides an API for several other sub-projects. You know, a mess. But the test base is still this old end-to-end super slow, I/O dependent monstrosity. Your team is only responsible for a single cogwheel in the huge machine, but what you test is actually the work of all 150 developers. This is great for KPIs, like code coverage, but does it help? Can you easily say what’s wrong with the code, if you only see one test failing? Probably not. Can you write a piece of code and then run all the tests locally, to check if everything is fine, before continuing with the next step? Strike that, can you run all tests on a designated server, while in the middle of developing the feature? Well is this test suite even helpful then? Not to you, no. It still has benefits, but you don’t have time to enjoy them. On top of all that, writing a new test might take a while. It requires knowing the workflows of the application and perhaps frameworks, which enable you to interact with the UI. And the application is not that small anymore. And if someone else messed up, your tests are failing. It doesn’t matter if you are not responsible, at the very least, you need to find who has to fix it.

All I said until now might be valid, but there should be tests, right? So where’s the solution. Well, your team is not the only one to write tests, right? Every team does (I hope). If that’s the case, why bother testing someone else’s code? That’s their job. But what if something fails, because they changed the API? They need to tell you on time. And if my pair programmer messed up and their part of the feature does not work with mine? No need to follow strictly this mantra, just establish borders. Integration tests are fine, just don’t integrate with the entire world. Besides, this old end-to-end test suite still runs overnight, right? The world wouldn’t crumble if the nightly build fails once or twice.

To summarize, always testing the entire code is not bad, but it’s slow both in execution and pinning down the problem. Fixing this problem is not hard, just write your tests such that they execute only your own code. Leave the rest to others. It’s their job. What this gives you, is not a fail-proof system, but a fast one. One, that ensures the logic of this particular module is sound and given the right inputs, produces the right results. Have a second tier testing, which executes nightly. It can cover everyone’s code and it probably should. It should make sure the most important workflows execute without a problem. This approach gives you the ability to „ALWAYS Test Your Code“ with ease, by practicing „Always Test YOUR Code“.

Alright, now you can start trusting other developers, so go on and test YOUR code!

Happy coding!