Over the last few years my blog has been filled with posts imploring testing and sharing techniques about testing. Most recently I’ve been speaking at code camps on how one can begin unit testing, sensing that a large majority of people out there don’t yet have the level of comfort with testing. Given my personal commitment to software quality through testing, I was excited to get my hands on a copy of Roy Osherove’s The Art of Unit Testing from Manning. A few weeks ago our copy was delivered and I have been excited for an upcoming vacation which would give me the time to sit down and churn through the book.
Part I – The Basics of Unit Testing
In part one Roy defines unit testing. Roy takes a similar approach as the one that I use, explaining early on that we all do unit testing in one form or another. Too often I hear from people that they don’t have time to unit test. The reality is, and Roy makes this point very well, is that we never hand over code right after writing it. We all take some time to “test”. Some people write unit tests. Some write a simple app to test various scenarios and yet others will run the whole application.
Roy takes the time early on to contrast a unit test with an integration test. This is a masterful move on Roy’s part as the confusion between unit testing and integration testing is one that even seasoned testers don’t always seem to understand. It sets the stage early and well for the introduction in part two of the use of isolation frameworks.
In this part of the book Roy introduces us to a sample application that carries us throughout the book. I always appreciate it when books do this. The consistent sample application allows the user to follow the addition of new concepts more easily than examples that jump around. Roy focuses solely on the NUnit framework which is something I plan to take with me when I give future talks on unit testing. In my talks I introduce users to NUnit, MbUnit, as well as xUnit. My thought process has been to inform the listeners of my talk to the different options available. After reading the book, Roy’s approach of presenting a single framework to the user is a much better approach. It allows the reader to go deeper with a single framework which will benefit the reader much more than the surface knowledge of several frameworks.
Part II – Core Techniques
This section goes into depth quite a bit on how to introduce “seams” (“…places in your code where you can plug in different functionality…”). I appreciate the effort Roy goes to in this chapter to explain how you exactly break apart your designs. He takes a methodical and thoughtful approach to design patterns that many out there have never used.
I was pleased to see the introduction of stubs as a concept outside of an isolation (mocking) framework. I take a similar approach when I talk about RhinoMocks and isolation frameworks. While Roy ends up talking about RhinoMocks (an isolation framework) he makes sure the reader understands why the framework is useful. Ultimately this is a benefit to the reader as they no longer become a drone using a framework advertised by a respected book author but instead are informed and make the decision based on what is best for their situation.
Roy also goes into detail about the differences between Stubs, Mocks and Fakes. These questions are something I encounter often when talking about “mocking”. The move towards simplicity and clarity was refreshing. In general for the mass public terms like “Test Doubles”, “Spys”, “Dummy”, “Fakes”, provide little to no value and only add confusion. Roy takes a similar stance and does a very good job clearing the air and setting the reader on a course for success.
As someone with a vested interest in RhinoMocks I was pleased to see it’s coverage in chapter 5. There were times where I questioned what Roy was doing (the introduction of strict mocks) but soon recovered with further explanation about the topic. I will say that I was not a fan of the use of the record/replay syntax in the book and the subsequent AAA syntax (which was really record/replay). I really can’t fault Roy on this because I believe that RhinoMocks 3.5 was released after Roy began working on the book.
Part III – The Test Code
This part of the book covered more of the non-code aspects to unit testing such a build automation, project structure, and inheritance for tests. In the beginning of the section Roy writes:
“In chapter 7, we’ll look at the three basic pillars of good unit tests – readability, maintainability, and trustworthiness – and look at techniques to support them. If you only read one chapter in the book, this should be it”
I questioned why this seemingly crucial chapter was in Part III of the book and not part of Part I (The Basics). Further, the importance of chapter 7 only appeared in the introduction to Part III and the reader would not find it unless they were already there.
Chapter 6 felt a bit out of place to me in the book. The inclusion of test class inheritance patterns isn’t something I see often in codebases nor the use of generics in tests, which was another pattern mentioned. Much of what was contained in this chapter seemed like common sense to me. I trust that Roy and the editors/reviewers of the book have seen enough instances to believe otherwise, hence the inclusion of this chapter in the book.
The information in chapter 7 was very good and I do agree with the statement (quoted above) that appeared in the introduction to the section. While I maintain the information may have served the reader better had it been presented in an earlier section it did not feel out of place or ruin the flow of the book.
Part IV – Design and Process
This section again is a section where the book undersells itself. Having spoken in the past about unit testing at several code camps, questions constantly comes up about the political aspects of testing. Developers question how they can bring it into their organization or how they can explain the benefits to other developers or even upper management. This section of the book does a great job at anticipating the common questions and how to best make unit testing efforts succeed. It addresses ways to help your unit testing efforts succeed and demonstrates ways that will cause those efforts to fail. Despite my previous adoption and enthusiasm for testing I still found the information in this section very useful and worthwhile.
Chapter 9 goes into testing legacy applications. The entirety of the book up to chapter 9 is spent on testing with the assumption that the developer has the ability to change/create the design. I believe this is a vast minority of people out there. Chapter 9 entices readers by talking about how to introduce testing into a legacy code base. The idea of graphing the priority of components in your system was something new to me but is very interesting and seems to be a thoughtful “scientific” way of attacking an untested legacy application. In general this chapter is shorter than I would have preferred but I believe that the majority of information that could be here would be out of the scope of this book which is why the chapter makes references to Michael Feathers' book Working Effectively with Legacy Code. (Not e to self: Buy Michael Feathers book)
Conclusion and Final Thoughts
This book is a must own, buy it. It covers unit testing from start to finish and will get you up to speed on unit testing rather quickly while giving you a solid foundation to build upon in the future. My only gripe with the book is that it generally undersells itself, which is a great position for a book to be in (the reader believing the book contains more value that was thought when the purchase was made).
I am generally not surprised that I enjoyed the book. I’ve closely followed Roy’s blog for several years and cut my unit-testing teeth on much of the advice contained on his blog. Roy is well respected in the community as well in the unit-testing circles and this book does the developer who reads it a great service in advancing their abilities in writing solid, testable code, a goal all of us should be striving after.
07-23-2009 11:16 AM