Test your code!

Test your code!

Software testing is littered with strong opinions and i'm no different. About the one dogma I'm guilty of - testing what you've built.

I have long felt the urge to address dogmatism in software engineering. As opinions have seemed to get more radical in developer communities, I had to add my 2 cents to a few of them. I pointed to some of the biggest beefs in the developer community - like unpopular design patterns, typescript or releasing on Fridays and tried to add some nuance to the discussions. I could finally sleep safe and sound again.‍

Until someone suggested writing an additional piece on testing. “What about addressing the ‘abolish unit tests’ clash?”

🤯

The TDD fan in me got triggered. I can understand people's reluctance to use TDD always and foremost, but abolishing tests is one step (way!) too far.

There it was - my very own dogma. I’m far from being alone, software testing is littered with very strong opinions.

Unit tests defenders vs. abolitionists

The unit testing squabble is one of the most controversial conversations in the community. Sometimes leading to hilarious exchanges like this one:

To be fair, there are some legit arguments against unit testing:

  • Unit tests can potentially if done wrongly, lead to unnecessarily fragmented and complex code. The emphasis on modularity and isolation can increase cognitive complexity and make it difficult to understand the code as a whole​​. The problem of how to make code testable is not trivial.

  • $$$ Although being small and isolated, and being cheaper than literally any other kind of test, they are still not free. They can become complex and time-consuming, especially when starting out with untested legacy code, where each unit test requires mocking half the codebase.

  • Unit tests often rely on implementation specifics, particularly when using mock-based testing. This leads to coupling issues, making refactoring more expensive and discouraging devs from making those necessary changes​​ quite as freely.

  • Real-world testing. They often miss out on testing how different parts of the software interact in a real-world scenario​​. In the end, what counts is that the code does what it’s supposed to in the customer’s context and not some isolated mocked unit test environment.

  • Overemphasis of their role at the cost of other test types. People might overlook the value of testing at higher levels, which reflect real user interactions better.

In my opinion, however, most of the criticism boils down to the wrong application of unit tests. Unit tests are often misunderstood and misapplied. For example, they don’t necessarily need to focus on a single file, object, or function, but rather on a unit of behavior, which can be more broadly defined​​.

I just think the arguments for unit testing are too solid to be ignored:

  • They identify bugs early before the issue snowballs into a larger problem as they are the first thing run before your code even hits any testing environment.

  • They help immensely with code refactoring. They make sure new code still performs as intended and that existing functionality is not broken by the changes. Running them continuously while changing the underlying implementation of the unit is the only way I feel confident enough in my own changes.

  • Documentation. Unless you’re a lonesome cowboy dev, someone else will look into your code at some point. Unit tests document how your code is supposed to be used. Great thing if someone else needs to wrap their head around it, or see the intended API usage of your piece of code.

Lonesome cowboy dev whose code is none of your business

* Lonesome cowboy dev whose code is none of your business

  • Unit tests are the fastest in the testing town. When applied correctly they speed up the entire development process. By catching bugs early and simplifying debugging, they reduce the overall time spent on troubleshooting and will in the long run absolutely make your lead time to changes go down as you will have the confidence to “just release”.

  • They improve code quality. They force devs to write more modular, maintainable, and understandable code. Of course, this only works if you treat unit test code as just as important as your production code - it should be part of your review process and standards enforced just the same.

Testing drill sergeants vs. let’s (maybe) test in production

The testing debate continues around the importance of tests in general. A small, vocal group of ‘move fast, break things’ devs advocate for releasing without testing, testing in production or even leaving the quality check to the users. I guess you can if the stakes are low enough and your users are forgiving.

testing in production meme

‍For me, this was the hardest part of questioning my own dogma. Ask any of my current or former colleagues, there’s one thing that I have been pretty dogmatic about in my career - testing your code. I’ve been likened to a “testing drill sergeant”.

‍I don’t think I’m quite as strongly opinionated about this anymore as I used to be. I don’t really care what level of the testing pyramid you choose to cover your code. I also am fine with tests growing along with the code: a prototype probably doesn’t need full coverage, while the full scalable production ready app does and I do think writing good tests is just as hard as writing good code (maybe even harder), so I understand the struggle.

If I’m allowed one ultimate developer opinion, please, test your code. It doesn’t have to suck. We try to help by making testing easier, so feel free to see if that can assist you in achieving the code quality you want.

---

Thanks for going through reading my 2 cents about dogmatism in software engineering Let me wrap up my dogma-busting with one last thought from the Pragmatic Engineer:

gergely orosz quote

So take it all with a grain of salt!

If you think I’m missing something or just want to chat about dogmatism, tests, AI or general startup engineering, you can find me here:

Daniel Draper
Lead engineer at Octomind