I recently had to define testing guidelines for my company and even though I already knew a fair bit about testing, I decided to start from the basics to see if I had missed anything or misunderstood certain concepts. It was also a good way to compare what I do in practice with the ideal approach.

A coworker recommended Unit Testing: Principles, Practices, and Patterns, a book that was already on his reading list. I found it valuable as it starts with the fundamentals and answers many common questions developers have about testing.

Learnings from the Book Unit Testing

Unit Testing book cover

Unit Testing book cover

Even with prior knowledge, I learned a few important things. Here are my top five takeaways from the book.

Classic vs. London Style

I wasn’t aware that there are two main approaches to unit testing, especially regarding mocking. These are known as the classic and London styles.

The London school focuses on isolating the system under test from all its collaborators. If a class has dependencies, they are replaced with mocks to ensure the test only evaluates the class itself.

The classic school takes a different approach, mocking much less. Instead of replacing dependencies with mocks, it uses production-ready instances, keeping tests closer to real-world scenarios.

All Code, Including Tests, Is a Liability

This wasn’t entirely new to me, but it served as a great reminder: we write code to solve business problems, and code itself has no inherent value and it’s a liability.

Tests are no exception. They are part of the codebase and exist to ensure the application works correctly. Like any code, they can have bugs and require maintenance.

Why Do We Test?

There are two main reasons for testing: to assess quality and to prevent known issues from reoccurring. For developers, testing also provides peace of mind.

When we modify code, we want to confirm that the new functionality works as expected. But just as importantly, we need to ensure that nothing else breaks in the process.

“You cannot trust yourself to do the right thing all the time—so, eliminate the very possibility of doing the wrong thing.” – Vladimir Khorikov

What Makes a Good Test?

A good test has four key attributes:

  • Protection against regressions: Ensures existing features still work after new changes.
  • Resistance to refactoring: Should remain valid even if the underlying code is refactored.
  • Fast feedback: Faster tests make it easier to catch and fix issues quickly.
  • Maintainability: Tests should be easy to understand and run.

Black-Box vs. White-Box Testing

Another key concept in test automation is the distinction between black-box and white-box testing.

  • Black-box testing examines a system’s functionality without considering its internal structure. It’s based on specifications and requirements, focusing on what the system does rather than how it does it.
  • White-box testing does the opposite. It verifies the internal workings of the system, deriving tests from the source code rather than from requirements.

According to the author, a test is either resistant to refactoring or it isn’t and there’s no middle ground. That’s why black-box testing should be the default choice. Regardless of the test type (unit, integration, or end-to-end) the focus should be on verifying behavior that matters to the problem domain. If a test doesn’t trace back to a business requirement, it’s a red flag. Either restructure or delete it, but don’t let it into the suite as-is.


This book reinforced some key principles while introducing me to new perspectives on unit testing. It’s a great read for anyone looking to improve their testing approach.

These are my learnings from the book Unit Testing: Principles, Practices, and Patterns by Vladimir Khorikov.

Cheers.