I first started reading Roy Osherove’s “The Art of Unit Testing” over a year ago, as my team was ramping up design and development of a new application to be written, in its entirety, in new technology (.Net framework 4.0, WPF, EF 4.0, etc). So new in fact, that when we started development, there was no “4.0” released, it was still at the Beta 2 stage. Also, since we were to be the first truly “agile” (scrum) team, we knew we had a lot of eyes on us, both from above as well as from fellow developers. By “truly agile” we were fairly close to textbook. We all worked in the same environment (shared room), including 3 developers (with one added for a 1.5 month stint to make up lacking capacity), manager/scrum master as well as QA. We had a CI environment which was setup and maintained. We had a scrum board, or boards, which were large 24” x 36” post-its or a wall when needed, filled with user stories, tasks, backlog, all diligently written and managed on post-it notes.
I knew that unit testing would be an important factor to our success, as well as a chance to revisit a sore topic. We had previously done the “unit testing thing” in our development organization during the development course of an important project, and it had left most of the developers with a bitter taste for it. I wasn’t certain of it at the time, but I knew we must have been doing something out of sorts at the time, specially after having heard and read so much about the virtues of unit testing from other great minds out there. Surely, they couldn’t all be addicted to and peddlers of a potion of pain!
After just the first 2 chapters, Roy had made all the points necessary for me to identify where our major pain points were at the time, based simply on the design of the project, its implementation, and our flawed understanding of the term “Unit Test”. We had no Isolation (mocking) Frameworks whatsoever, everything knew how to do everything it needed to do its job, but wasn’t focussing on actually fulfilling its purpose!
We were also very much testing that the code we wrote behaved as we wrote it, rather than how we expected it to work. If you’ve ever heard Roy or anyone else passionate about testing speak, or read their works, this is a fatal flaw. This would be the equivalent of an actor getting punched in the face for a scene, take after take, and the director giving it his approval time after time, without considering that perhaps the true expectation is that it should only look like the actor’s being punched. It may all be the same to the director and almost everyone involved, but for both the punch giver and the punch recipient, the difference may be rather notable!
The more I read, the more I was determined to take the topic to heard, and make it work. Design Patterns would be acknowledged and used when appropriate. Inversion of Control would be primordial, not only for testability, but also just made sense from a design perspective. Units would be tested, objects would get their test doubles, and the project would be successful.
Unfortunately for myself, and to a certain extent for the project, as the project grew and deadlines approached, I had to set aside the book in order to shift the focus of my time on delivery. By that time, I had just gotten to the start of Chapter 5, and really starting to understand the full power and versatility of Isolation Frameworks. In hindsight, I wish that I had found a way to find make the time needed to at least read fully through the first five chapters before calling for a time out.
Chapter 5, it turns out, would be the pivotal chapter in my understanding of the entire unit testing “ecosystem”, not just when an isolation framework is involved, but as a whole. Isolation frameworks and I had tangoed before, and I had co-workers who had also worked with them, but our collective understanding of their use and purpose was as mis-guided as our organization’s original attempt at unit testing. Mocks and stubs would be used interchangeably. Record/Replay (RR) methodology would be intermingled with Arrange/Act/Assert (AAA), sometimes within the same test class, if two people happened to have worked on it at different times.
Though the project was, and still is, a success, that success did come at a cost, which was partly paid during the beta phase. Since we had lapsed in developing unit tests in parallel to the code needed for new functionality as we needed it, we ran into several complexity and logic issues when the time came to debug, enhance and re-factor these pieces of code. Though the older and tested pieces of code also had some issues, it was much easier to backfill and enhance the test code as we revisited it, since we already had a testing foundation set for it.
Later chapters include more invaluable hints and gold nuggets of information and practices, including testing legacy code, structuring your tests in ways that enhance test code reuse (DRY applies to all code, not just product code), explaining what exactly is a good test, and how to write them. He also touches on integrating unit testing into your development organization, as well as giving a brief yet thorough overview of a good number of tools related to unit testing. This includes testing frameworks, isolation frameworks, Inversion of Control (IoC) and Dependency Injection (DI) containers and a number of other testing utilities for various situations (multi-threading, UI, web, etc).
In summary, buy this book, and READ it! At least the first five chapters and harness the knowledge within them before you need it (p.s.: you already need it!) Whether you’re on a project that needs tests today, will be on a project a month from now, or even if you were on a project which was laden with defects which “should have been caught”, or simply because you want your work to be better, without shadow of a doubt, this book can and will help you!
It has gained a permanent place on this developer’s bookshelf, and a digital copy is always at hand in case I need a quick refresher.