Preface
Over a dozen years ago I read Refactoring for the first time; it immediately became my bible. While Refactoring isn’t about testing, it explicitly states: if you want to refactor, the essential precondition is having solid tests. At that time, if Refactoring deemed it necessary, I unquestionably complied. That was the beginning of my quest to create productive unit tests.
Throughout the 12+ years that followed my first reading of Refactoring I made many mistakes, learned countless lessons, and developed a set of guidelines that I believe make unit testing a productive use of programmer time. This book provides a single place to examine those mistakes, share the lessons learned, and provide direction in a way that I’ve found to be the most effective.
Why Test?
The answer was easy for me: Refactoring told me to. Unfortunately, doing something strictly because someone or something told you to is possibly the worst approach you could take. The more time I’ve invested in testing, the more I’ve found myself returning to the question: Why am I writing this test?
There are many motivators for creating a test or several tests:
- validate the system
- immediate feedback that things work as expected
- prevent future regressions
- increase code-coverage
- enable refactoring
- document the behavior of the system
- your manager told you to
- Test Driven Development
- improved design
- breaking a problem up into smaller pieces
- defining the “simplest thing that could possibly work”
- customer acceptance
- ping pong pair-programming
Some of the above motivators are healthy in the right context, others are indicators of larger problems. Before writing any test, I would recommend deciding which of the above are motivating your testing. If you first understand why you’re writing a test, you’ll have a much better chance of writing a test that is maintainable and will make you more productive in the long run.
Once you start looking at tests while considering the motivator, you may find you have tests that aren’t actually making you more productive. For example, you may have a test that increases code-coverage, but satisfies no other motivator. If your team requires 100% code-coverage, then the test provides value. However, if your team has abandoned the (in my opinion harmful) goal of 100% code-coverage, then you’re in a position to perform my favorite refactoring: delete.
Who Should Read This Book
This book is aimed at a professional programmer, someone who writes software for a living. The examples and discussion include a lot of code to read and to understand.
Although this book is focused on testing, testable code can have a large impact on the design of a system. It is vital for senior designers and architects to understand the principles recommended and to use them in their projects. The principles within this book are best introduced to a team by a respected and experienced developer. Such a developer can best understand the principles and adapt them to their specific context. In addition, familiarity with this book’s content will allow experienced developers to provide it as a reference for the less experienced members of their team.
Despite my opinion on who should introduce these concepts, I’ve attempted to write this book for both people experienced with and those brand-new to unit testing. Ideally, a respected programmer will look to implement the ideas within this book, and begin by passing this book on to those on the team that would likely share interest in this approach. If you’re already writing tests I believe this book will provide concepts and suggestions that will prove useful for years to come. If you aren’t already writing tests you’ll likely want to pick up an intro to unit testing book as well. The concepts in this book should be understandable to developers of all levels; however, we will not cover concepts such as framework selection, framework configuration, or writing your first test.
Building on the Foundations Laid by Others
While this book does contain an Acknowledgments section, it wouldn’t be practical to thank everyone that has contributed to creating the practices that this book details. I can say with full confidence that I wouldn’t be in the position to write this book without at least the following groups:
- creators and maintainers of both NUnit and JUnit
- creators and maintainers of NMock, (James Mead’s) Mocha, Mockito, JMock, and RSpec
- each team member from each of my projects at ThoughtWorks & DRW Trading
- every conference speaker or attendee who’s provided feedback on my (sometimes radical) ideas
- every person who left a comment on blog.jayfields.com
Thank you all, I deeply appreciate the feedback you’ve given throughout the years.