The vertebrate immune system rivals the most intricately engineered security system on a bad day, detecting and destroying most microorganisms that we encounter on a daily basis within minutes or hours . Occasionally a pathogen will breach the early lines of defense and require what is called an adaptive immune response. The front-line warriors of this response are your B cells, which are activated during the adaptive immune response (becoming plasma cells) and secrete hundreds to thousands of antibodies per second per cell . These antibodies contribute to the immune response by either disabling the pathogens, signaling macrophages to destroy the pathogens, or triggering other immune responses . Activated B cells will often differentiate into "memory cells," which can survive for years, or even a lifetime. Both plasma cells and memory cells are antigen-specific, meaning the recognize and produce antibodies for a specific pathogen. The presence of memory cells in the bloodstream allows for a much quicker immune response upon encountering a pathogen in the future .
So what does all of this have to do with software?!?!
I happen to manage the development of software supporting life sciences research, and I love the opportunity to draw parallels between seemingly orthogonal concepts. In this case, you, the software developer, are your software's immune system!
First of all, let's consider the first line of defense, the so called "innate immunity" . It recognizes pathogens almost immediately upon entry to the body. This is, of course, your test-driven developed suite of unit tests. Track with me:
- Write enough test to fail;
- Write enough code to pass;
- Refactor, rinse, repeat.
Your software's innate immunity first kicks in during step number three. The goal of refactoring is to improve the design of existing code without changing its behavior. Any change in behavior would be considered a pathogen, henceforth referred to as "a bug."
If you're test-driving the development of your code, you're going to have darn near 100% coverage by unit tests. This test suite will immediately detect any bugs that enter your code and force you to remove them. This can be during the refactoring phase, or much further down the line when implementing other features. Aided by your continuous integration system (Hudson, CruiseControl.NET) configured to run your entire test suite after each code check-in, your test suite provides an excellent innate immune response system for your software.
However, even those of us that are "test infected" (how ironic is that label in an article like this one?) will have bugs creep through this first line of defense. Sooner or later you'll get the call from QA (or elsewhere) that a bug has shown up. It's time to invoke the adaptive immune response!
We need to create a memory cell that is specific to this particular bug, one that will trigger an immediate response (i.e. a failed build) should it ever crop up again. What better way to do that than with an automated test? Before you spend even a moment of your time correcting your production code, write a test that will reproduce the bug and fail. Then spend your time making that test pass. Now, any time you or another unsuspecting developer inadvertently reintroduces the bug, your test suite will catch it immediately. If you continue this practice throughout your software's lifecycle, your test suite will continuously adapt to each bug and become more and more robust. The next time any of these bugs crop up, they won't make it to QA - your software won't get sick! My fellow zone leader here at Agile Zone, Jared Richardson, calls this Defect Driven Testing (DDT).
So, just as a well-engineered immune system is necessary for a healthy organism, so too a well-engineered test suite is necessary for healthy software. Happy testing!
 C. Janeway, P. Travers, M. Walport, M. Shlomchik. Immunobiology, 5th Ed. New York: Garland Science; 2001.