Unit tests are part of the software development drill. At the same time, the benefits of writing them can be unclear, especially when you’ve never worked on a project with a decent test coverage. In this article, I’ll walk through what I see as the main benefits of unit tests for developers working alone and in teams.
The first situation to consider—a developer working on a personal project, without help from other people. Here, it depends a lot on your goals with the project. If you are building a little application for fun, adding unit tests may not make much sense. For more serious projects, adding unit tests can bring you the following benefits.
Test-driven development (TDD) is a programming workflow in which all the changes are done in the following loop:
- you write a test case that checks the behavior of the code you are about to write—the test fails because the code is not written yet (red),
- you write the missing code, so the test can pass (green),
- you improve the code, with assurance from unit tests that your code is behaving exactly in the way you meant it (refactor).
If you follow this workflow every time you code, you will produce complete test coverage because no code will be written before writing relevant tests. Besides that, it allows you to work with a very short feedback loop, as you run tests all the time and verify whether they pass or fail as expected.
I find this approach helpful when I know what code I need to write. On the other hand, it’s not helpful for exploring alternative solutions—after all, writing code and tests is more writing than the code alone. After I find a solution that works fine, I can comment it out and then write tests that will force me to uncomment my code.
For me, one of the biggest benefits of unit testing is its impact on code architecture. While writing unit tests, the boundaries of different units are very visible—things that are not part of the unit are often mocked so that the test stays focused on only one part of the code. Keeping the code testable forces you to keep the units small and well isolated. When your classes grow too much and keep too much responsibility, the complexity of covering them with tests will grow exponentially.
Over the years, I developed an intuition for what code is testable and what is not. But when I was starting out, writing unit tests was often a struggle, requiring me to reorganize my code into smaller, more testable units.
Finally, writing unit tests in your personal project is a great exercise. On the job market, there are companies that are serious about testing and companies that are not, so learning to write unit tests can feel optional. I find places that focus on quality (including testing) more pleasant to work at. Unit tests allow teams to constantly verify their code and, by doing so, catch bugs early. And this leads to fewer issues at production and less stress—which makes a better workplace.
Another set of unit tests benefits appears when you start working with other people.
Unit tests are a perfect way to document what code is supposed to do. They allow you to show what output is expected for a given input and a given state. Contrary to code comments, you can be sure unit tests are up-to-date—because they would be failing otherwise. Unit tests are an additional layer of communication between the code author and people who will later change the code.
Especially when working with less experienced developers, I find it very helpful to have an extensive test coverage that verifies their changes. Instead of depending on more experienced people finding issues in juniors’ code, juniors will get feedback from continuous integration. And when they finish writing a pull request that passes all the tests, it’s way easier to review it when both code and test changes are available.
If you are interested in learning more, you can sign up here for updates from me when I publish new articles on testing or other programming topics.