The word “test” in software is a very loaded term. The first time I came across a tester (as in, a person performing the quality assurance role) was in my first professional job. We were never taught about testing at college, as we were all there to learn to be “developers”.
It turns out there are lots of different kinds of testing. In a series of blog posts titled Agile Testing Directions, Brian Marick came up with a 2x2 matrix of test types, and describes the activities which happen in each corner of the matrix. If you haven’t read the blog posts, they can help to provide a vocabulary about the kinds of testing that most software teams undertake.
A lot has changed in the nearly 6 years since Brian wrote those posts. Test Driven Development is arguably the most well known and most popular part of the eXtreme Programming software development process. For several years, I’ve been giving talks and coaching teams on how to do Test Driven Development, and by far the most frustrating part of the process has been overcoming people’s expectations when you use the word “test”. For most developers, “testing” is something that’s done by “testers”, not something that’s done by developers. Even those developers who are savvy enough to be doing unit testing are still practicing an activity whose primary purpose is quality assurance.
What the name Test Driven Development has going against it is that it doesn’t properly express the purpose of TDD; namely, that it is a process designed to help you drive and iterate the design of your implementation at the unit level. The result of the design process is unit tests, but their primary purpose is not one of quality assurance; rather, it is an expression of the intended usage of the component under design. In this way, the “tests” that you are writing become the first client of your component, and come into being just before the component’s code is written. The rhythm in TDD is “write a test, watch it fail; write the production code, watch the test now pass; when prudent, refactor the code to increase clarity and remove duplication”.
The unit tests written by TDD have some quality assurance value as a secondary effect of the test, but that is not their primary goal. Their primary goal is to help you design the code, and to give you a safety net with which to refactor your code. Note that when I use the word refactor, I mean it in the classical sense: to change the internal implementation of a component without changing its externally observable behavior; that is, if you find yourself needing to change a unit test, you are not doing refactoring.
Frustrated by the misunderstanding of the purpose of TDD, my friends and I (Peter, Jim, Brian, Scott, and many others, all agile practitioners and coaches) decided to start calling it Test Driven Design. A small change, but it starts to focus on the fact that the process is about design. Unfortunately, that “test” word baggage is still in there, so our next iteration was then Example Driven Design. This worked well too, but “EDD” and “TDD” were still too close together and confusing.
The final iteration ended up being Design By Example (DbE). Now when I talk about TDD, I always call it Design By Example, and explain why we like this name better than TDD. Where TDD(esign) or EDD failed to get traction, people really seem to resonate to Design By Example.
~ ~ ~
As an aside, you’ll note that most of the unit testing frameworks on .NET have the word “test” in them a lot. NUnit started this with the [Test] attribute, which MbUnit adopted, and MSTest converted into [TestMethod]. When Jim and I set out to design xUnit.net, it originally had a [Test] attribute in it as well, which is how it was when we first talked about it publicly at the first ALT.NET event in Austin. Even before ALT.NET, we’d been lamenting the name [Test] for the attribute exactly because of this baggage with the word “test”. We wanted xUnit.net to be a framework that was first and foremost for TDD (erm, DbE) practitioners.
At the Austin event, we decided to rename [Test] to [Fact]. While some users have complained that this is an arbitrary change, we felt it was right because it removed the focus of the word “test” from the code that you were writing when doing DbE. It also lined up very well with the [Theory] feature we added to xUnit.net Extensions to support David Saff’s data theories. The essential difference is: a [Fact] is an expression of some condition which is invariant, whereas a [Theory] is an expression of a condition which is only necessarily true for the given set of data. As such, [Theory]s are driven with external data; if you provide invalid data, then the theory will potentially produce invalid results.
An example of a [Fact] is the condition which says, “if you have failed to properly initialize this object, when you call this method on it, it will throw InvalidOperationException”. There are no variations on this rule; it is always true. An example of a [Theory], using the classic FizzBuzz interview question, is the condition which says, “if you pass a number which is divisible by 3, but not by 5, the result should be ‘Fizz’.” For this theory, you pass values which meet the initial requirement; if you were to pass 4 or 15, though, the result would be a failure, but that doesn’t mean the theory is bad, it simply means the preconditions for the theory weren’t properly met.