About this book

Developer testing has been increasing its mindshare significantly among Java developers over the past 10 years or so. Today, no computer science student graduates without having at least read about automated unit tests and their importance in software development. The idea is simple—to ensure that our code works and keeps working—but the skill takes significant effort to learn.

Some of that effort goes to simply writing tests and learning the technology such as a test framework like JUnit. Some of that effort (and quite possibly most of it) that’s required for truly mastering the practice of writing automated unit tests goes to reading test code and improving it. This constant refactoring of tests—trying out different ways of expressing your intent, structuring tests for various aspects of behavior, or building the various objects used by those tests—is our pragmatic way of teaching ourselves and developing our sense for unit tests.

That sense is as much about what good unit tests are like as it is about what not-so-good unit tests are like. There may be some absolute truths involved (such as that a code comment repeating exactly what the code says is redundant and should be removed) but the vast majority of the collective body of knowledge about unit tests is highly context-sensitive. What is generally considered good might be a terrible idea in a specific situation. Similarly, what is generally a bad idea and should be avoided can sometimes be just the right thing to do.

It turns out that often the best way to find your way to a good solution is to try one approach that seems viable, identify the issues with that approach, and change the approach to remove the icky parts. By repeating this process of constantly evaluating and evolving what you have, eventually you reach a solution that works and doesn’t smell all that bad. You might even say that it’s a pretty good approach!

With this complexity in mind, we’ve adopted a style and structure for this book where we don’t just tell you what to do and how to write unit tests. Instead, we aim to give you a solid foundation on what kind of properties we want our tests to exhibit (and why) and then give you as many concrete examples as we can to help you develop your sense for test smells—to help you notice when something about your test seems to be out of place.

Audience

This book is aimed at Java programmers of all experience levels who are looking to improve the quality of the unit tests they write. While we do provide appendices that teach you about a test framework (JUnit), our primary goal is to help Java programmers who already know how to write unit tests with their test framework of choice to write better unit tests. Regardless of how many unit tests you’ve written so far, we’re certain that you can still get better at it, and reading a book like this might be just what you need to stimulate a line of thought that you’ve struggled to put into words.

Roadmap

Effective Unit Testing takes on a multifaceted challenge that calls for a structure that supports each of those facets. In our wisdom (gained through several iterations of failed attempts) we’ve decided to divide this book into three parts.

Part 1 begins our journey toward better tests by introducing what we’re trying to achieve and why those goals should be considered desirable in the first place. These three chapters present the fundamental tools and simple guidelines for writing a good test.

Chapter 1 starts off with the value proposition of automated unit tests. We establish the value by considering the many things that factor into our productivity as programmers and how well-written automated unit tests contribute to that productivity or prevent things from dragging us down.

Chapter 2 sets the bar high and attempts to define what makes a test good. The properties and considerations in this chapter serve as the core foundation for part 2, touching on how we want our tests to be readable, maintainable, and reliable.

Chapter 3 steps out of the line for a moment to introduce test doubles as an essential tool for writing good tests. It’s not really using test doubles that we’re after but rather using them well and with consideration. (They’re not a silver bullet in case you were wondering.)

Part 2 turns the tables and offers a stark contrast to part 1 in its approach, presenting a catalog of test smells you should watch for. Along with describing a suspect pattern in test code we’ll suggest solutions to try when you encounter such a smell. The chapters in this part are divided into three themes: smells that suggest degraded readability, smells that indicate a potential maintenance nightmare, and smells that reek of trust issues. Many of the smells in part 2 could be featured in any of these three chapters, but we’ve tried to arrange them according to their primary impact.

Chapter 4 focuses on test smells that are primarily related to the intent or implementation of a test being unnecessarily opaque. We touch on things like illegible assertions, inappropriate levels of abstraction, and information scatter within our test code.

Chapter 5 walks through test smells that might lead to late nights at the office, because it takes forever to update one mess of a unit test related to a small change or because making that small change means we need to change a hundred tests. We take on code duplication and logic in our test code and we expound on the horrors of touching the filesystem. And it’s not like we’re giving a free pass to slow tests either because time is money.

Chapter 6 concludes our catalog of test smells with a sequence of gotchas around assumptions. Some of these assumptions are made because there’s an inconvenient comment in our test code and some are the unfortunate products of a failure to express ourselves unambiguously.

Part 3 could have been called “advanced topics.” It’s not, however, because the topics covered here don’t necessarily build on parts 1 or 2. Rather, these are topics that a Java programmer might stumble onto at any point on his or her test-writing journey. After all, almost everything about “good” unit tests is context-sensitive so it’s not surprising that a pressing topic for one programmer is a minor consideration for another, whether it’s about inheritance between unit test classes, about the programming language we use for writing tests, or about the way our build infrastructure executes the tests we’ve written.

Chapter 7 picks up on where chapter 2 left off, exploring what constitutes testable design. After a brief overview of useful principles and clarifying how we are essentially looking for modular designs, we study the fundamental testability issues that untestable designs throw our way. The chapter concludes with a set of simple guidelines to keep us on the righteous path of testable design.

Chapter 8 throws a curveball by posing the question, what if we’d write our unit tests in a programming language other than Java? The Java Virtual Machine allows the modern programmer to apply a number of alternative programming languages and integrate it all with plain Java code.

Chapter 9 returns to common reality by taking on the challenge of dealing with increasingly slow build times and delayed test results. We look for solutions both within our test code, considering ways of speeding up the code that’s being run as part of our build, and in our infrastructure, pondering whether we could get that extra bit of oomph from faster hardware or from a different way of allocating work to the existing hardware.

Despite JUnit’s popularity and status as the de facto unit test framework within the Java community, not all Java programmers are familiar with this great little open source library. We’ve included two appendices to help those individuals and programmers who haven’t squeezed all the horsepower out of JUnit’s more advanced features.

Appendix A offers a brief introduction to writing tests with JUnit and how JUnit pokes and prods those tests when you tell it to run them. After skimming through this appendix you’ll be more than capable of writing tests and making assertions with JUnit’s API.

Appendix B takes a deeper dive into the JUnit API with the goal of extending its built-in functionality. While not trying to cover everything about JUnit to the last bit of detail, we’ve chosen to give you a brief overview of the two common ways of extending JUnit—rules and runners—and devote this appendix to showcasing some of the built-in rules that are not only useful, but also give you an idea of what you can do with your custom extensions.

Code conventions

The code examples presented in this book consist of Java source code as well as a host of markup languages and output listings. We present the longer pieces of code as listings with their own headers. Smaller bits of code are run inline with the text. In all cases, we present the code using a monospaced font like this, to differentiate it from the rest of the text. We frequently refer to elements in code listings taken from the text. Such references are also presented using a monospaced font, to make them stand out. Many longer listings have numbered annotations that we refer to in the text.

Code downloads

The Manning website page for this book at www.manning.com/EffectiveUnitTesting offers a source code package you can download to your computer. This includes selected parts of the source code shown in the book, should you want to take things further from where we left off.

The download includes an Apache Maven 2 POM file and instructions for installing and using Maven (http://maven.apache.org) to compile and run the examples. Note that the download doesn’t include the various dependencies, and you need to have an internet connection when running the Maven build for the first time—Maven will then download all the required dependencies from the internet. After that, you’re free to disconnect and play with the examples offline.

The code examples were written against Java 6, so you’ll need to have that installed in order to compile and run the examples. You can download a suitable Java environment from www.oracle.com. (To compile the code, you’ll need to download the JDK, not the JRE.)

We recommend installing a proper IDE as well. You may want to download and install the latest and greatest version of Eclipse (www.eclipse.org) or another mainstream tool like IntelliJ IDEA (www.jetbrains.com) or NetBeans (www.netbeans.org). All of these should work fine as long as you’re familiar with the tool.

What’s next?

This book should give you enough insight to start visibly improving your unit tests. It’s going to be a long journey, and there’s bound to be a question or two that we haven’t managed to predict or answer in full. Fortunately, you’ll have plenty of peers on this journey and many of them will be more than happy to share and discuss the nuances of test code online.

Manning has set up an online forum where you can talk to the authors of Manning titles. That includes the book you’re reading right now so head over to the Author Online forum for this book at www.manning.com/EffectiveUnitTesting.

There’s also an active community of test-infected programmers over at the testdrivendevelopment and extremeprogramming Yahoo! Groups. While these forums aren’t exclusively for discussions about unit tests, they are excellent places for holding those discussions. Besides, maybe you’ll manage to pick up some new ideas outside of test code, too.

If you’re looking for a more focused forum for having discussions about developer testing, head over to the CodeRanch at http://www.coderanch.com and the excellent Testing forum. Again, a lovely group of very helpful people over there.

Most importantly, however, I suggest that you actively talk about your test code with your peers at work. Some of the best insights I’ve had about my code have been through having someone else look at it on the spot.

Author Online

Purchase of Effective Unit Testing includes free access to a private web forum run by Manning Publications, where you can make comments about the book, ask technical questions, and receive help from the author and from other users. To access the forum and subscribe to it, point your web browser to http://www.manning.com/EffectiveUnitTesting. This page provides information on how to get on the forum once you are registered, what kind of help is available, and the rules of conduct on the forum.

Manning’s commitment to our readers is to provide a venue where a meaningful dialogue between individual readers and between readers and the author can take place. It is not a commitment to any specific amount of participation on the part of the author, whose contribution to the book’s forum remains voluntary (and unpaid). We suggest you try asking the author some challenging questions, lest his interest stray!

The Author Online forum and the archives of previous discussions will be accessible from the publisher’s website as long as the book is in print.