TDD Tests are not Unit Tests

The motivation for this blog entry is to explain the nature and purpose of the tests used in Test-Driven Development. To avoid confusion, I’ll use the expression TDD test to refer to the type of test used in the context of Test-Driven Development. The goal of this blog entry is to clarify the relationship among TDD tests, unit tests, and acceptance tests.

TDD Tests are not Unit Tests

Let’s start with the distinction between TDD tests and unit tests. On the surface, TDD tests are very similar to unit tests. This is not surprising, since you use a unit testing framework such as Visual Studio Tests or NUnit to create both types of tests.

The purpose of a unit test is to test a unit of code in isolation. For example, you might create a unit test that verifies whether a particular class method returns the value that you expect. The standard example of a unit test is a test that verifies the Add() method of a Math class (see Listing 1).

Listing 1 – Math.cs

public class Math
{
    public int Add(int val1, int val2)
    {
        return val1 * val2;
    }
}

Listing 2 – MathTests.cs

[TestClass]
public class MathTests
{

    [TestMethod]
    public void TestAdd()
    {
        // Arrange
        var math = new Math();

        // Act
        var result = math.Add(2, 3);

        // Assert
        Assert.AreEqual(5, result);
    }
}

The Add() method in Listing 1 is intended to add two numbers together (but was badly written).

The unit test in Listing 2 verifies that 2 + 3 does, in fact, equal 5. If the Add() method is not implemented correctly then the unit tests fails (see Figure 1).

Figure 1 – Failing unit test

clip_image002

In real life, the situation is rarely as simple as this Math example. Typically, a class has many dependencies on other classes. For example, the class in Listing 3 contains validation logic. However, it also calls into a data access class and a logging class. In these cases, you must resort to faking or stubbing the dependent classes.

Listing 3 – Validation.cs

public class Validation
{
    private ForumsRepository _repository = new ForumsRepository();
    private Logger _logger = new Logger();


    public void CreateForumPost(ForumPost post)
    {
        // Validate forum post
        if (String.IsNullOrEmpty(post.Subject))
            throw new Exception("Subject is required!");

        // Store forum post in database
        _repository.CreateForumPost(post);

        // Log it
        _logger.Log("Add new forum message");
    }

}

In a well-designed application, each class has a single responsibility (the SRP principle). A validation class contains only validation logic, a data access class contains only data access logic, and so on. When creating unit tests, you test whether a class satisfies its responsibilities. For example, when unit testing a validation class, you don’t test data access logic. A unit test for the validation class should verify whether the validation logic behaves in the way that you expect.

The purpose of a unit test is to give a developer confidence that a particular part of their application behaves in the way that the developer expects. This is very valuable for regression testing. If you modify code that is covered by unit tests, then you can use the tests to immediately determine whether you have broken existing functionality.

So how does a TDD test differ from a unit test? Unlike a unit test, a TDD test is used to drive the design of an application. A TDD test is used to express what application code should do before the application code is actually written.

Test-Driven Development grew out of a reaction to waterfall development. One important goal of Test-Driven Development is what Kent Beck calls incremental design and what Martin Fowler calls evolutionary design. Instead of designing an application all at once and up front, an application is designed incrementally test-by-test.

When practicing Test-Driven Development, you develop an application by performing these steps over and over again:

1. Create a failing test

2. Write just enough code to pass the test

3. Refactor your code to improve its design

This process is called Red/Green/Refactor because a unit testing framework displays a red bar for a failing test and a green bar for a passing test.

When practicing Test-Driven Development, the first step is always to create a failing test. You use the test to express how you want your code to behave. For example, when building a forums application, you might start by writing a test that verifies whether or not you can post a new message to the forum.

When you write a TDD test, you write the test without making any design decisions up front. Fowler writes:

Classicists, however, think that it’s important to only think about what happens from the external interface and to leave all consideration of implementation until after you’re done writing the test.

http://martinfowler.com/articles/mocksArentStubs.html#DrivingTdd

When writing a unit test, you should only consider what you want your application to do. After you write the test, you make implementation decisions. Finally, after implementing enough code, you consider how you can refactor your application to have a better design.

A TDD test, unlike a unit test, might test more than a single unit of code at a time. Fowler writes:

Unit testing in XP is often unlike classical unit testing, because in XP you’re usually not testing each unit in isolation.

Fowler http://www.artima.com/intv/testdriven4.html

As the design of your application evolves, code that was originally contained in one class might end up in multiple classes. Unlike a unit test, A TDD test can test code that spans multiple classes.

TDD Tests are not Acceptance Tests

A customer acceptance test (also known as an integration test or a functional test) is used to verify that an application behaves in the way that a customer expects. An acceptance test is usually created in collaboration with a customer as an way of determining whether the customer requirements have been met.

The audience for an acceptance test is different than the audience for a TDD test. An acceptance test is created for the benefit of the customer. A TDD test, on the other hand, is created for the benefit of a developer.

Unlike a TDD test, an acceptance test is not created with a unit testing framework. Instead, customer acceptance tests are created with an acceptance testing framework such as Selenium, Fit, FitNesse or Watir/WatiN.

These acceptance testing frameworks enable you to test an application end-to-end. For example, using Selenium, you can simulate posting an HTML form to a web server. Then, you can verify that a particular response was returned by the web server (you can pattern match text returned in the response).

One important difference between a TDD test and an acceptance test is that everything is hooked up when you perform an acceptance test. You perform an acceptance test against the actual web server and database server.

TDD tests, on the other hand, need to execute very fast. You should execute your TDD tests each and every time that you make a change to your code. Because an application might include hundreds (or even thousands) of TDD tests, individual TDD tests must be fast.

Kent Beck has something he calls the 10 minute rule. You should be able to execute all of your TDD tests in less than 10 minutes (and still have time to drink a cup of coffee). If you are running your TDD tests against an actual web server or database then you won’t be able to satisfy the 10 minute rule.

What is a TDD Test?

The best way to understand the purpose of a TDD test is to understand the purpose of Test-Driven Development. According to Fowler:

TDD’s origins were a desire to get strong automatic regression testing that supported evolutionary design.

http://martinfowler.com/articles/mocksArentStubs.html#DrivingTdd

First, TDD tests – like unit tests — support regression testing. You use TDD tests to quickly verify whether you have broken existing application functionality whenever you make a change to the application code. This support for regression testing makes incremental design possible by enabling you to continuously refactor your application. You can mercilessly refactor your application to have a better design because you have the safety net of unit tests.

Second, TDD tests – like acceptance tests — are used to drive the design of your application. TDD tests act as mini-acceptance tests. A TDD test expresses the task that you need to do next and the criterion for success.

There are several good walkthroughs of Test-Driven Development including:

o Bowling Score Example – Included in Robert and Micah Martin’s excellent book Agile Principles, Patterns, and Practices in C# and partially reproduced here http://www.objectmentor.com/resources/articles/xpepisode.htm.

o Currency Conversion Example – Included in Kent Beck’s excellent book Test-Driven Development by Example.

o Bookmark Collection Example – Included in James Newkirk’s blog. This is a series of posts that describe building a Bookmark Collection.

When practicing Test-Driven Development, you start with a list of user stories that describe, in a non-technical way, how an application should behave. These user stories are developed in collaboration with the customer for the application. Each user story should be, at most, a few sentences long.

In Kent Beck’s walkthrough, he keeps a list of tasks that looks very much like a task list. Implementing one task inspires him to add additional tasks to the list. When he creates a test that corresponds to the task, and implements the code necessary to pass the test, he crosses the task off his list.

For example, when building a forums web application, you might start with the following list of user stories:

· A user should be able to create a new forum post. A forum post includes an author, subject, and body.

· A user should be able to view all of the forum posts on the home page. The latest posts should appear higher than earlier posts.

· A user should be able to reply to an existing post.

· A user should be able to select a particular post and see the post and all of the replies.

This list of user stories evolves as you write the application and you get additional feedback from the customer. You use this initial list of user stories as a starting point.

Next, you pick a user story to implement. Your TDD tests should flow out of the user story. For example, imagine that you pick this story to implement:

· A user should be able to create a new forum post. A forum post includes an author, subject, and body.

In that case, you might start with a TDD test that looks like Listing 4. The test in Listing 4 verifies that you can add a new post to the forums application.

Listing 4 – ForumControllerTests.cs

[TestMethod]
public void ForumPostValid()
{
    // Arrange
    var controller = new ForumController();
    var postToCreate = new ForumPost();

    // Act
    controller.Create(postToCreate);
}

 

The test verifies that you can invoke the Create() action on the Forum controller with a new forum post. After you write the test, you can implement the application code required to satisfy the test. In this case, you would need to create a ForumController and ForumPost class.

After you create this first test, and write the code to satisfy the test, you will think of other related tests. For example, you might want to verify that posting a forum message without a subject generates a validation error message. The test in Listing 5 verifies that a validation error message is added to model state when you attempt to post a message without a subject.

Listing 5 – ForumControllerTests.cs

[TestMethod]
public void ForumPostSubjectIsRequired()
{
    // Arrange
    var controller = new ForumController();
    var postToCreate = new ForumPost { Subject = string.Empty };

    // Act
    var result = (ViewResult)controller.Create(postToCreate);

    // Assert
    var subjectError = result.ViewData.ModelState["Subject"].Errors[0];
    Assert.AreEqual("Subject is required!", subjectError.ErrorMessage);
}

The point here is that the TDD tests are flowing directly from the user stories. The TDD tests are acting like mini-acceptance tests. You are using the TDD tests to drive the building of the application.

Conclusion

The goal of this blog entry was to clarify the difference among TDD tests, unit tests, and acceptance tests. A TDD test is similar to both a unit test and an acceptance test, but it is not the same.

Like unit tests, TDD tests can be used for regression testing. You can use TDD tests to immediately determine whether a change in code has broken existing application functionality. However, unlike a unit test, a TDD test does not necessarily test one unit of code in isolation.

Like acceptance tests, TDD tests are used to drive the creation of an application. TDD tests work like mini-acceptance tests. You create a TDD test to express the application functionality that needs to be implemented next. However, unlike an acceptance test, a TDD test is not an end-to-end test. A TDD test does not interact with a live database or web server.

Discussion

  1. Jedidja says:

    You obviously do not understand the subject you’re writing about. For all the programmers out there who are just learning the craft, please just delete this post. It has so many errors in it it’s difficult to know where to begin commenting.

  2. Michael says:

    Personally, I found it informative.

  3. So do i. Very informative

  4. Rob Conery says:

    I think I see the point you’re after, but the title (and the bit about UA and integration tests) is confusing.

    I would agree that, traditionally speaking, unit testing may product tests that are a bit different than their TDD cousins. TDD tends to be a bit more verbose and, when effectively done, you can see the “footprints” of the builder of the app.

    Traditional testing probably would be written in a “does this work” sense. So I would agree there’s a qualitative “flavor” difference – but in each case you’re trying to focus on a small element of code – a “unit” if you will and I think it might be more accurate to say that both focus on unit tests – but unit tests don’t mean you’re doing TDD (which I think we all understand :).

    Acceptance tests aren’t unit tests – I’ll agee there. These are criteria for “green lights” or “going gold” – they are the minimum criteria for beta to release and they’re focus is application experience.

    Integration tests span all kinds of things and usually focus on “can my app work in X environment with X system”. I’d agree that these aren’t unit tests either.

    Is this what you’re trying to say?

  5. Brad Wilson says:

    I would appear that you’ve muddled two different kinds of design into a single thing in your mind.

    First is the design of application qua user (usually expressed as user stories), and is usually a collaborative process led by the product owner (or the customer representative, in XP terms). This activity happens before any work is done and before any tests are written. In XP terms, this is the work done before the iteration planning meeting happens, usually resulting in story cards for the team. Any resulting “test code” from this kind of design application is called automated functional testing, and although you can do it with a traditional unit testing framework, there are many efforts to find a more reasonable expression of these higher level concepts (for example, FIT or SWIM). In Brian Marick’s 4 quadrants of testing[1], this is the upper left quadrant[2].

    The other type of design is the design of components qua components. This is the kind of design that’s driven by TDD, which is a proscription for the way in which you can practice unit testing to drive component design. In most agile processes like XP, the design of components is not something that is decided ahead of time, primarily because deciding on implementation details before implementation is error-prone and time-consuming. The result of TDD is unit tests. In Brian Marick’s 4 quadrants of testing, this is the lower left quadrant[3].

    Unfortunately, your blog post seems not to make any distinction between the two. I believe this muddling is what has caused you to believe that TDD is yet a third type of testing separate from unit testing and functional testing. I’ve never found that to be true, personally, and I’ve used both TDD and acceptance testing for several shipped projects over a span of many years.

    [1] http://is.gd/rYOZ
    [2] http://is.gd/rYPb
    [3] http://is.gd/rYPA

  6. @Brad — I’m confused by your comment. You seem to be agreeing with everything that I write in the blog entry about acceptance tests and then you conclude that I am muddled :)

    I’m not alone in making this distinction between unit tests and TDD tests. Martin Fowler writes:

    “Unit testing in XP is often unlike classical unit testing, because in XP you’re usually not testing each unit in isolation.”

    Fowler also writes “In essence classic xunit tests are not just unit tests, but also mini-integration tests.”

    I echo this last statement by Fowler in the blog entry. If you are practicing Test-Driven Development then TDD tests are related, but not exactly the same, as standard unit tests.

  7. Brad Wilson says:

    Stephen, your out of context quote doesn’t actually support the entire set of ideas that Martin is describing in that interview.

    “Testing each class and it’s immediate connection to its neighbors” is testing classes in isolation, through the process of substituting “fake” neighbors into the system so that you can closely monitor and manipulate those relationships.

    I’m curious why you seem to repeatedly appeal to authority rather than talk about what your own real world experiences have been. Have you used TDD extensively to develop shipping applications?

  8. Hi Stephen,

    I have not excluded the possibility that you made this post for the express purpose of getting people to make comments, and if that is indeed its purpose then I admit I took the bait.

    I really think you should reconsider this post. Take just one of your many statements:

    “a TDD test is used to drive the design of an application”

    Yikes!

    I know you’re the author of many books, and I don’t want to show disrespect. But Stephen as a reader of this post, and a proponent, writer, and speaker about unit testing and TDD, I have to say that the way you compartmentalize TDD into a third arena of testing (separate from unit testing) is incorrect.

    By your own definition of unit testing:

    “The purpose of a unit test is to give a developer confidence that a particular part of their application behaves in the way that the developer expects.”

    you are describing precisely what TDD is all about.

  9. @Russ — A TDD test does not necessarily meet the technical definition of a unit test. A unit test tests a unit of code in isolation (typically a single method). However, often my TDD tests perform a test against multiple classes at a time.

    I start with a user story and my unit tests flow from the user story. For example, I might want to test whether creating a forum post without a subject causes a validation error message to be added to model state. The test begins life as a test against a single controller class (a unit test). But, as my design improves test-by-test and I migrate my validation logic into a service layer, that test ends up testing multiple classes. The unit test has transformed into a mini-acceptance test because it is testing multiple classes.

    I realize that people create tests in very different ways. The methodology that I describe has worked well for me.

  10. Hi Stephen,

    If your TDD tests are testing multiple classes at a time then I would submit that your particular TDD tests are flawed. But that’s just my opinion.

    My TDD tests, which are unit tests, do not cross class boundaries. This serves as a great way to promote isolation. When they do, they become what I call integration tests, because they are testing more than one unit.

    If you do it another way that works for you, go for it! :)

  11. Slim Amamou says:

    I agree that the term “unit” may be confusing. Agile developers acknowledge that, and prefer the use of the term “developer test”

    http://c2.com/cgi/wiki?DeveloperTest

    There is no distinction between developer tests. They depend on the project and on what you want to test, not on an intrinsic property of the test itself.

  12. Rob Conery says:

    @Stephen I have to echo what Brad is asking you repeatedly quoting Martin and Uncle Bob is not going to sell your point. Those quotes are not in context.

    A Unit Test is a *very* broad term – TDD is a practice, *not a test type*. TDD focuses on isolated test cases to drive design, unit testing is a part of that.

    Back to my original question: what’s your point on all this? You’re making a statement: “TDD Tests are Not Unit Tests” and sort of leaving out the “therefore…”.

    I’d like to see some clarity here because other commenters are offering you very, very concrete arguments and you’re offering them links and quotes. Help me out – I’m starting to get links on my blog about this post and I really don’t want to have to spend much more time on this – so can you please be a bit more declarative with your purpose here? In other words: “OK – confusion and semantics. So what?”

  13. Yazid says:

    Hello,

    Sorry use a link:

    http://www.hanselman.com/…/…signTheLastWordOnTDD.aspx

    ScottB says that Test Driven Development is less about Testing and more about Design.

    I think the T in TDD is misleading.

    Regards
    Yaz

  14. Hi Stephen,

    Are you that sure? I mean TDD stands for test-driven development – a practice of writing tests before the actual code. But it’s not said that you have to write any particular kind of tests.

    Thus, I think saying “TDD tests” is a bit incorrect.

  15. Yiyi Sun says:

    Let me guess, in your next post, you might say
    “TDD Tests are not Unit Tests. TDD Tests are Specification Tests.” and lead readers to BDD.

    en.wikipedia.org/wiki/Behavior_Driven_Development

  16. In my experience TDD does not work this way at all.
    You’re right that you write tests before making any design decisions. But that does not mean that these tests span more units.

    In many cases tests drive design-changes of more than one unit but that does not mean the test needs to span units!

    You write a test, try to implement code, discover that another unit needs to change too, and that’s where stubbing comes in! You stub the behaviour of the other unit. Make the test you’re writing go green, refactor, and then write a new test to drive the design change in the other unit.

    When you start writing tests that depend on more than one unit your tests become brittle, every time you change the design of your application more and more tests start failing. You can only prevent this by making tests fail for one reason and make one test fail for that reason.

  17. @Yaz – Thanks for the link! I agree with Bellware when he writes:

    “I think that it’s also quite sad though….that no matter how often it was brought up, or how often it was pointed out, or even requested, the folks to really consider TDD as design rather than testing-that it never really sank in; and I find this fascinating.

    “…the goal here with Test Driven Development isn’t really a unit testing goal although we’re borrowing unit testing tools to achieve the goal…we’re borrowing testing, almost like we’re sort of demonically possessing unit testing to achieve other means.”

  18. @Russ — I agree that creating a test that spans multiple classes makes the test more brittle — it can make it more difficult to isolate the location of a defect. However, in practice, it is not as bad as it sounds. If you run your tests after each code change, you can be pretty confident that it was the very last change that introduced the defect and caused your existing tests to fail.

  19. @Russ — I agree that creating a test that spans multiple classes makes the test more brittle — it can make it more difficult to isolate the location of a defect. However, in practice, it is not as bad as it sounds. If you run your tests after each code change, you can be pretty confident that it was the very last change that introduced the defect and caused your existing tests to fail.

  20. Rob Conery says:

    Hi Stephen – I can snip quotes from 100 different places to assert that ScottGu is Willy Wonka and I’m the Easter Bunny :). I’m very very interested in what your point is with this article (other than “there’s a difference” – I think that’s fairly obvious). I’ll be honest with you in that so far this reads as a pastiche of quotes and references – I don’t know what you’re trying to add to the coversation and I’m rereading and rereading and I can’t tell.

    Are people testing wrong? Is the design of ASP.NET MVC wrong? Are we all misguided for thinking that we’re writing Unit Tests when doing TDD (and if so, how)?

    This is important to me because it runs right up against my last screencast, which was focuses squarely on testing – and I’m being asked repeatedly about this article. I’m trying to figure out the point here – but right now all I can say is “I’m not sure what Stephen’s saying – I’ll ask him”.

    So – my “assertion” :):) is that “TDD Tests” as you call them are, in fact, unit tests however they are written different than they’re “traditional” unit test breathren (let’s call them “TAD Tests”). Could you Would you tell me if/why I’m wrong sir?

  21. @Rob — I’m glad you think the point that there is a difference between TDD tests and unit tests is “fairly obvious” :) This point might be obvious to you and me, but I keep running into discussions in which people equate Test Driven Development with simply creating unit tests for their application.

    The point of this blog entry is to emphasize that TDD tests are different than unit tests. TDD is first and foremost a design methodology. If you are not writing tests to drive the design of your application (using incremental design) then you are creating unit tests and not TDD tests.

  22. EricTN says:

    Reading the comments to this blog post and your last one certainly demonstrate one thing: TDD and definitions/discussions around it provoke very strong, passionate, even religeous reactions from fellow developers. I just hope you continue doing what you do – I think you are a terrific teacher and when I watch one of the talks you do, you really have a knack for making things clear. You have a great fluid style in your presentations.

  23. Haacked says:

    Hi Stephen, I think most TDD practitioners would agree that the purpose of TDD is not the same as the purpose of just writing unit tests for testing purposes. TDD has a purpose, to design the code. It’s a developer design activity.

    Thus the focus of TDD is not testing is a correct thing to say. However, the artifacts produced by TDD are indeed what most people would characterize as unit tests. They may not share the same purpose, but the end result is that the tests produced share nearly all other qualities of unit tests. So they aren’t that different.

    For example, your own examples somewhat contradict what you’ve written. You mention that the so called TDD test should not depend at all on implementation details. But how in the world did that ForumPost come into existence?

    What if I swap out the DefaultModelBinder with my own SimpleModelBinder because I don’t want the form posts to automatically map to an object.

    Now your TDD Test needs to change because it makes no sense. It has implicit knowledge that when the user submits a forum post, somehow that post gets mapped to a ForumPost instance and not something else.

    Or, I might choose to implement a particular user story using Web Forms, an implementation detail. Again, your “TDD Test” would not make sense in that scenario because it’s tied to ASP.NET MVC action methods.

    It seems that you haven’t really drawn much of a distinction of what the two tests actually look like in practice, just in what the purpose of tests are.

    A unit tests doesn’t need to know the internal implementation details of the unit under test, but it does need to understand how that unit fits in with other units. For example, what dependencies it has and what the expected behavior of those dependencies are. That’s where mocking often comes into play, and what Fowler was referring to.

    Fowler was referring to the fact that the Mockist wants to ensure that the code under test calls methods on the mock in the correct order on a mock. That’s the internal implementation details you don’t want in a unit test. The classist just wants to make sure the unit under test fulfills its behavioral requirements per its public API and doesn’t care which order methods are called. The mock is thus really just a fake that fakes the behavior of the dependency that the unit under test requires to do its own job.

  24. Haacked says:

    In this post and the last, you’ve attempted to describe what TDD is and isn’t, but you haven’t yet discussed whether you think it’s really effective.

    We can’t just assume TDD is effective as a development tool as is. There might always be room for improvement.

    It’d be interesting to hear your thoughts on how effective you’ve found TDD to be. How many real projects (aka paying customers or production apps) have you applied this technique to where you found it to really improve your designs? It’d be interesting to hear how your history and experience applying TDD has led to better designs.

  25. @Phil — You and I are in agreement that TDD tests and unit tests have a different purpose. This point might seem obvious to you and me — but I have discovered that it is not an obvious point to others.

    I agree with the proponents of Behavior Driven Development that the word Test in Test-Driven Development just confuses everyone. If this whole blog topic was discussed by using the word Specification instead of Test, then there would be far less passion and confusion.

  26. Rob Conery says:

    OK, now you’re getting under *my* skin too. You can twist words and contexts all you like – but don’t play that game with me – it’s beneath you. I don’t agree with you – have the decency to see my point and respond.

    I’m *not* agreeing with you on this. I said this, three times, specifically: “TDD tests are unit tests”. Unit testing *in the traditional sense* (let’s call it TAD) can differ in flavor and yes, that’s obvious – you pointed it out (although incorrectly) in your last post.

    A point is *not* “there’s a difference* – that’s not a point. A point is when you add a “therefore” at the end of an assertion and I’ll ask you again: what is it you’re trying to say here, cause it’s lost on me and you’re making us all look a bit silly.

  27. PK says:

    /me is glad he is wearing a helmet because this is blowing his mind.

  28. born2code says:

    semantics aside, I think you drive home your distinction between testing after the fact (unit testing) and testing before implementation (what you call TDD). I also get that your title refers to this distinction and nothing else.
    You may want to change the title to satisfy the purists, but I for one get what you are saying.

  29. EricTN says:

    “The motivation for this blog entry is to explain the nature and purpose of the tests used in Test-Driven Development.” That’s the first sentence in the blog post. There’s no level-400 point being made by the post because it’s a level-100 post. Just for beginners, to get a feel for the “driven” part of the TDD acronym. At least that’s what I got out of it.

  30. Drew Miller says:

    It’s clear that TDD is not equivalent to unit testing. I don’t think anyone will dispute that. But that doesn’t mean that a so-called “TDD test” is not a “unit test”. Sure, there might be cases where a “TDD test” tests more than one type or method, or has a scope larger than a “unit”. But the vast majority of “TDD tests” (at least in my experience) will meet the same criteria that makes a “unit test”. Mr. Walther’s categorical assertion that “TDD tests” differ from “unit tests” is a good example of “cherry picking.”

    Additionally, seasoned TDD practitioners know that a testable unit is not necessarily a type or method; at times, the smallest testable unit has a larger scope than that (albeit rarely). That’s actually the “design” part of TDD: designing your implementation so that the simplest, smallest, and most testable unit of development is delivered according to expectation, and that it will continue to execute as expected.

    TDD is not an application design technique! TDD does not drive the design of an application (the “what”); it drives the design of the implementation ( the “how”). Every time I’ve seen TDD used beyond that boundary, I’ve seen spectacular failure. I’ll always have a story in hand (or implicitly in mind) when I sit down and start development using TDD. I might organize and define my tests along the lines and language of the story (as in BDD), but I’m still designing the “how” of the application, not the “what”. Naturally, my understanding of the “what” will change over time, at times as a result of my tests. But it’s not my tests’ responsibility (or primary purpose) to shape the “what.”

    Regarding EricTN’s statement that this is a level-100 post, I have to disagree. A level-100 ‘blog post should be helpful to neophyte TDD partitioners. It should help them to start the fundamental practice of: write test, write code, refactor, and repeat. A discourse on the nature of tests isn’t helpful to the beginner. In fact, as with this ‘blog post, it muddies the issue, quite possibly confuses the reader, and in no way motivates them to take up the practice. The comments about this ‘blog post being informative and helpful worry me, because I don’t think the information presented here will lead to better TDD.

    That said, “you don’t have to take my word for it.” I’m not a TDD expert, and neither is Mr. Walther, If you’re a beginner, I urge you to consider Jedidja’s advice, and just move along. Sadly, if you’ve read this far, it’s probably too late.

    So, instead, I urge you to find a complete source of information from a recognized TDD expert (such as a book), presented in its full context, and give it careful consideration. If you’re not already practicing TDD today, start now! It really is a game-changing practice, even if one that takes time to learn and do well. If you are already a TDD practitioner, I doubt you made it this far.

    Cheers,
    Drew