Experiences of an Inland Empire Dad

What Makes a Good Unit Test?

A good unit test should be:

Many DevTest teams require developers to include unit tests for the functionality they add or change during a commit, but are then often surprised to find bugs that are only exhibited in the wild. This is because unit tests only exercise small portions of the system in isolation; they are necessary, but not at all representative of how an entire system will function.  However, they are also the foundation of the testing pyramid.  We don’t want to “throw garbage over the wall” to our QA or Ops group to find what might be relatively simple bugs that bring down our system or cause it to behave is ways we don’t want.

Things to avoid when making testable code

As developers, when we write our code, we should keep in mind that unit tests are an integral part of our jobs, and as such, avoid some common pitfalls that make our code hard to test, such as:

Static Properties and Fields

Static properties and fields or, simply put, global state, can complicate code comprehension and testability, by hiding the information required for a method to get its job done, by introducing non-determinism, or by promoting extensive usage of side effects. Functions that read or modify mutable global state are inherently impure.

Singletons

Essentially, the Singleton pattern is just another form of the global state. Singletons promote obscure APIs that lie about real dependencies and introduce unnecessarily tight coupling between components. They also violate the Single Responsibility Principle because, in addition to their primary duties, they control their own initialization and lifecycle.

The new Operator

Newing up an instance of an object in order to get some job done introduces the same problem as the Singleton anti-pattern: unclear APIs with hidden dependencies, tight coupling, and poor testability.

Static Methods

Static methods are another potential source of non-deterministic or side-effecting behavior. They can easily introduce tight coupling and make our code untestable.

Conclusion

Obviously, writing testable code requires some discipline, concentration, and extra effort. But software development is a complex mental activity anyway, and we should always be careful, and avoid recklessly throwing together new code from the top of our heads.