Unit Testing Exposed: Why You Might Be Wasting Your Time!

Keagan Ladds
7 min readJun 28, 2024

--

Introduction

This article does not serve as a definitive answer or guide on unit testing but rather as an open conversation about when and when not to use it. The world of software development is diverse, and so are the practices surrounding unit testing. I personally don’t think there is a one-size-fits-all approach to unit testing; instead, it varies based on the situation and type of project. This article will explore different aspects of unit testing, its importance, and considerations to help you make informed decisions about implementing unit tests in your projects.

What is Unit Testing?

Imagine your software application as a car. This car is made up of many individual parts: the engine, wheels, brakes, etc. Each part must work correctly on its own before it can contribute to the smooth operation of the entire car. Unit testing is like inspecting and testing each individual part of the car to make sure it works perfectly on its own before putting it all together. In the context of software, it means checking the smallest pieces of the software (called “units”), such as individual functions or methods, to ensure they are working correctly.

Why Should You Unit Test?

Unit testing is a crucial practice in software development that ensures each component or unit works correctly on its own. Unit testing has the following the following advantages:

  • Quality Assurance: It ensures that each part of the software works as intended. Just like you wouldn’t want to find out the brakes are faulty after the car is built, we don’t want to discover issues in the software after it’s fully developed.
  • Cost-Effective: Finding and fixing problems early (at the unit level) is much cheaper and easier than dealing with them later when the software is already built and integrated.
  • Reliability: By thoroughly testing each unit, we reduce the risk of software failures, leading to more reliable and trustworthy applications.
  • Confidence in Software: Just as you’d have more confidence in a car knowing each part has been tested, you can have more confidence in thoroughly unit-tested software.
  • Faster Development: Problems are identified and fixed early, reducing the time spent on debugging and fixing issues later in development.
  • Higher Satisfaction: Reliable, well-tested software leads to happier users and customers, which can improve your business’s reputation and customer satisfaction.

Unit Testing Centric Software Development

A handful of software development methodologies exist that primarily focus on unit testing. That is, unit testing takes priority from day one, and functional code is developed around unit tests. Some developers and middle managers strongly assert that this is the best and only way to create good software. I like to think everyone is entitled to their opinion, even if it’s wrong.

A prime example of such methodology is Test-Driven Development (TDD). In this methodology, unit tests are written before any functional code. All the unit tests are expected to fail at this stage because the logic still needs to be implemented. The logic is then implemented and refactored until all the unit tests pass. This approach ensures your codebase is always testable and encourages better design practices from day one. However, this approach is not always feasible. Unit tests are not free; just like functional code, writing good tests takes time and effort. In the early stages of an agile project, requirements are bound to change. This leaves you with not only functional code to update but also unit tests.

Things To Consider When Approaching Unit Testing

In a perfect world, a project's requirements would be unambiguous, the source code would have 100% code coverage, and my parents wouldn’t think that I was a disappointment. Hell, unit testing wouldn’t even be needed because bugs wouldn't technically be possible. But the reality is that software development occurs in an environment of ever-changing requirements and disappointed parents, and as such, there is no one-size-fits-all solution to anything. This includes an approach to unit testing. Whether you’re starting on a new project or working on an existing one and considering whether unit testing should be a priority, consider the following questions.

Is Unit Testing Really Needed

In general, I agree with the common notion that unit testing is a software development best practice and is always needed. However, there are cases in which unit testing does not make sense and is not worth the effort. If any of the following apply, I would recommend making unit testing a priority:

  • The project needs to be maintained in the future — unit testing can help identify newly introduced bugs, and spending the time and effort to implement unit tests now can help save time in the future.
  • The project has functionality critical to health and/or safety—this is a no-brainer for me. If the logic in the project has any health or safety implications, it should be thoroughly covered by unit tests.
  • The project has functionality critical to business operation—functionality that could potentially have negative financial or reputational consequences for the company should it behave unexpectedly should be thoroughly tested. You wouldn’t want to miss a bug that incorrectly charges a customer six times.

In short, if you have a short-lived project with no safety or business criticality, go ahead and skip unit tests. It’s very likely not worth the effort. In the end, unit tests cost time and money. If you can get away with saving money without burning yourself or anyone else in the future, why the hell not? I can already hear the horde of middle managers who have once read a book on agile development gasping at my scandalous suggestion.

Source — Tenor

What Should You Aim For

Telling your engineering team that you want 100% code coverage on a legacy project and that it should be done by the end of the month is a great way to test HR’s employee offboarding process.

Once you've decided to prioritize unit testing, the next question is how much of the code should be tested and to what extent. Of course, the idealist answer would be “all of it!”. However, as I have noted earlier, unit testing costs time and money. And realistically, 100% code coverage is asking for a lot, even on a greenfields project. You should aim to find a balance between spending time on writing functional code that provides value today and unit testing which will provide value in the future. In the case of a software development house, for example, there is little value in only writing unit tests; the client is paying for the value the functionality provides and would want to see that as soon as possible. However, not writing unit tests at all will likely cost more money down the line due to having to debug and fix bugs that would have otherwise been picked up by unit tests.

That being said, my short answer to this question is to unit test as much code as possible that makes business sense.

When During a Project’s Lifecycle Should You Prioritize Unit Testing

Focus on unit testing in the beginning stages of a project with changing requirements, and you’ll spend more time fixing broken unit tests than writing code. Leave unit testing until the end of the project, and you’ll need to refactor all the code and introduce bugs while just trying to make the code testable. These are two extremes which, from experience, I would recommend avoiding.

There is no correct answer to this question; it depends on the project or situation. The key, in essence, is trying to balance adding unit tests late enough in the project lifecycle so that maintaining them to keep up with changing requirements won’t cause too much overhead and adding them early enough in the project lifecycle to ensure that adding them does not require significant refactoring of the code to make it testable.

How To Achieve Unit Testing Goodness

Okay, you finally realize that you want to unit test your code; your next question might be, where to go from here? Here are some things to consider on your path to getting yourself some of that unit-testing goodness:

  • Automate — ensuring your unit tests are run automatically will allow developers to get feedback on tests that fail quickly.
  • Measure — you can’t track progress over time without measuring progress, so ensure you’re measuring important unit testing metrics such as code coverage and condition coverage. Also, make sure that you’re measuring the right thing. Unit test code coverage metrics on projects containing only POCOs don’t make sense.
  • Set goals — setting goals on unit testing metrics such as code and condition coverage. Be realistic about what coverage you expect and the timeframes. Getting a decently sized project from 0% to 80% code coverage will not happen overnight. And while setting a 100% code coverage goal is excellent, unless you’re willing to spend significant time on unit testing, this isn’t realistic.
  • Enforce — preventing pull requests from being merged with failing tests helps prevent unwanted bugs from making it to production. Enforcing code coverage thresholds on newly committed code ensures that new features are covered by tests.

Conclusion

Unit testing, like many other practices in software development, is a tool that should be used judiciously. It offers significant benefits regarding quality assurance, cost-effectiveness, reliability, and overall confidence in the software. However, it is essential to recognize that it is not always necessary or feasible to implement unit tests universally. The decision to prioritize unit testing should be influenced by your project's specific needs and constraints, including its criticality, longevity, and the potential impact of defects.

By aiming for a balanced approach that considers the practicalities of your development environment, you can leverage unit testing's strengths without overcommitting resources. Ultimately, unit testing should be seen as a strategic investment in the long-term health and success of your software rather than a rigid mandate.

Like, Share and Subscribe

If you enjoyed this article, I would really appreciate it if you shared it. If you would like to read more of my content in the future, please follow me.

--

--

Keagan Ladds
Keagan Ladds

Written by Keagan Ladds

Software engineer @ Tesla & serial tinkerer, writing about the tech things that keep me up at night.

Responses (1)