The Art of Unit Testing
Buy it now
One Minute Bottom Line
|The book is called The Art of Unit Testing, but it's really about the craft. It's a practical, soup-to-nuts guide to implementing effective unit testing.|
The Art of Unit Testing, by well-known .NET developer Roy Osherove, is an excellent resource for developers interested in using unit tests to their full potential.
While the book provides an introductory chapter on the basics of unit testing and the NUnit framework used in the examples, it’s probably not the best book for someone who has not previously worked with unit tests. A lot of the techniques and suggestions Osherove provides can’t really be appreciated until you’ve written some tests and run into frustrations.
The meat of the book is divided into three sections. The first section deals with writing testable code and using stubs and mocks to simulate dependencies in unit tests. The second section deals with techniques for writing more efficient and effective tests. The third section provides advice on making unit testing an integral part of your organization’s development process and dealing with testing legacy code that was not written with unit testing in mind.
I found the first section particularly useful, in part because, unlike many who write about unit testing, Osherove isn’t a devotee of test-driven development or a staunch advocate of dependency-injection/inversion-of-control frameworks. While he discusses the topics, he takes a very pragmatic approach, taking into account how the development and deployment of libraries and applications currently works in most organizations. He provides multiple ways of making code testable, and discusses the pros and cons of each.
One approach I really found useful, as someone who finds the constructor-injection and property-injection methods of removing dependencies to be inelegant, is “extract and override”, which Osherove says he sometimes calls “ex-crack and override” due to it being such an easy habit to get into. The method allows you to build testable code without necessarily needing to make changes to a class's public API, which I find very appealing, as someone who generally likes to follow an object-oriented approach.
Also coming from an object-oriented point of view, I really appreciated a section of the book where Osherove addresses concerns that testable code breaks encapsulation. He suggests looking at the test as an end user of a class's API, with the same importance as the class’s actual users. In this approach, which Osherove calls “testable object-oriented design” or “TOOD”, the changes are features that expand the class to address the needs of this second end user, rather than a corruption of the model that serves the original end user. I found this perspective to be very helpful in removing my discomfort with changing classes to enable easier testing. For those who might still be uncertain, Osherove also provides some other suggestions to allow you to make even fewer changes to a class’s design.
The book dedicates several chapters to stubs and mock objects. Mocks and stubs are a critical part of effective unit testing, but presumably some of the emphasis is influenced by the fact that Osherove currently is the chief architect at TypeMock, which develops the powerful (and pricey) TypeMock Isolator mocking software. Despite that association, the book's examples use the free RhinoMocks framework, although Osherove does take time to tout some of the unique features TypeMock provides. The suggestions and techniques he provides for effectively using stubs and mocks are extremely useful, and provide a good overview of how to handle testing different situations and relationships between pieces of code.
The second section of the book is fairly unique among books on unit testing. Instead of focusing on how to test your code, it focuses on the tests themselves as maintainable, reusable code. He discusses building a test API for an application that provides easy, consistent access to frequently-used methods and patterns to all of the application’s tests, as well as ways to provide standard suites of tests for various types of methods.
Another part of this section I found valuable was the discussion of how to write tests that are trustworthy – in other words, tests that will pass only when the code they test works, and fail only when the code they test doesn’t. When tests are trustworthy, they’re less likely to be ignored and more likely to be maintained. A failure won’t be glossed over as an expected issue.
The third main section of the book provides suggestions for implementing unit testing in an organization and making it an integral part of your development process. I’m fortunate in that my current employer is very enthusiastic about unit testing, but some of my previous employers have been more resistant, and the suggestions Osherove provides would likely have been quite useful in overcoming that resistance.
The book concludes with an appendix that provides an overview of the major testing tools available for .NET developers, including unit-testing frameworks, dependency-injection containers, mocking frameworks, and tools for database, UI, and Web testing. I found the outlines he provided of the strengths and weaknesses of the various tools to be very helpful.
I would definitely recommend that any developer who is serious about writing better code read The Art of Unit Testing. While it might not be the definitive guide to all aspects of unit testing, it’s a unique resource for learning how to test effectively.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)