In the last couple of years, there’s been a lot of debate in the community on the philosophy behind TDD and where to put the emphasis – even to the point of debating whether the acronym stands for Test-Driven Development or Test-Driven Design.
Other people don’t like the emphasis on tests, since that makes TDD sound like a Testing discipline, and not a Development discipline. Instead, they prefer terms like Example-Driven Design/Development (EDD) or even Design by Example (DbE).
This view seems to me to be particularly prevalent in Microsoft, where there’s a rather sharp distinction between developers and testers (job titles to the contrary) – I guess that’s one of the reasons why xUnit.net (a project initiated by Microsoft employees) uses the attribute Fact instead of Test or TestMethod.
For people used to SCRUM or other agile methodologies, this distinction is more blurred, and they also seem to accept the T in TDD more willingly.
However, the adherents of EDD claim that the mere presence of the word test make some developers block any further input and stop listening. They may be right in that.
They also claim that the tests in TDD/EDD are nothing more than accidental artifacts of the development process, and hence argue that we shouldn’t call them tests at all. However, if that’s true, this little story related by Ayende must be an example of EDD in its purest form :)
To me, the tests are also important. Since 2003 I’ve been practicing TDD, and while I love how it helps me arrive at better design, I also savor the safety net that my suite of tests gives me. The tests that I write during TDD define the behavior of the software. In many cases, I’d even claim that such a regression test suite is more valuable than a Quality Assurance (QA) regression test suite – after all, a QA suite may catch some edge cases, but they don’t focus on the intended behavior of the system, but often more on how to break it - but I digress…
My recent posts on Executable Specification and Constrained Non-Determinism help explain my current stance in this debate: In my opinion, EDD fails to establish a relationship by not providing Derived Values. After all, what does a test like the following specify?
[TestMethod]
public void InvertWillReverseText_Naïve()
{
// Fixture setup
MyClass sut = new MyClass();
// Exercise system
string result = sut.Invert("ploeh");
// Verify outcome
Assert.AreEqual<string>("heolp", result, "Invert");
// Teardown
}
How would you implement the Invert method? Here’s one possible implementation:
return "heolp";
Obviously, you could now write a new test that gives a second example of input and outcome and force me to write a more sophisticated algorithm. However, with only two examples, I might still be tempted to write a switch statement with some hard-coded return values until you’ve written so many ‘examples’ that you’ve coerced me into writing the more general (and correct) algorithm.
Such an approach I find inefficient.
Instead, by using Constrained Non-Determinism to force myself to define Derived Values, each test fully specifies the desired behavior. It doesn’t provide examples. It provides the specification, and instead of having to write several similar examples to coerce a general algorithm to emerge, I can usually nail it in a single test.
This approach could be styled Specification-Driven Development, and that’s how I’ve been writing code for the last year or so.
Remember Me
a@href@title, b, em, i, strike, strong
Page rendered at Saturday, February 04, 2012 10:12:51 PM (Romance Standard Time, UTC+01:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.