Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

These are Robert C. Martin's rules for TDD:

  • You are not allowed to write any production code unless it is to make a failing unit test pass.
  • You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  • You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

When I write a test that seems worthwhile but passes without changing production code:

  1. Does that mean I did something wrong?
  2. Should I avoid writing such tests in the future if it can be helped?
  3. Should I leave that test there or remove it?

Note: I was trying to ask this question here: Can I start with a passing unit test? But I wasn't able to articulate the question well enough until now.

share|improve this question

3 Answers 3

up vote 12 down vote accepted

It says you can't write production code unless it's to get a failing unit test to pass, not that you can't write a test that passes from the get-go. The intent of the rule is to say "If you need to edit production code, make sure that you write or change a test for it first."

Sometimes we write tests to prove a theory. The test passes and that disproves our theory. We don't then remove the test. However, we might (knowing that we have the backing of source control) break production code, to make sure that we understand why it passed when we didn't expect it to.

If it turns out to be a valid and correct test, and it isn't duplicating an existing test, leave it there.

share|improve this answer

It means that either:

  1. You wrote the production code that fulfills the feature you want without writing the test first (a violation of "religious TDD"), or
  2. The feature that you need happens to be already fulfilled by the production code, and you're just writing another unit test to cover that feature.

The latter situation is more common than you might think. As a completely specious and trivial (but still illustrative) example, let's say that you wrote the following unit test (pseudocode, because I'm lazy):

public void TestAddMethod()
{
    Assert.IsTrue(Add(2,3) == 5);
}

Because all you really need is the result of 2 and 3 added together.

Your implementing method would be:

public int add(int x, int y)
{
    return x + y;
}

But let's say I now need to add 4 and 6 together:

public void TestAddMethod2()
{
    Assert.IsTrue(Add(4,6) == 10);
}

I don't need to rewrite my method, because it already covers the second case.

Now let's say that I found out that my Add function really needs to return a number that has some ceiling, let's say 100. I can write a new method that tests this:

public void TestAddMethod3()
{
    Assert.IsTrue(Add(100,100) == 100);
}

And this test will now fail. I must now rewrite my function

public int add(int x, int y)
{
    var a = x + y;
    return a > 100 ? 100 : a;
}

to make it pass.

Common sense dictates that if

public void TestAddMethod2()
{
    Assert.IsTrue(Add(4,6) == 10);
}

passes, you don't deliberately make your method fail just so that you can have a failing test so that you can write new code to make that test pass.

share|improve this answer
3  
If you followed Martin's examples fully (and he doesn't necessarily suggest that you do), to make add(2,3) pass, you would literally return 5. Hard-coded. Then you would write the test for add(4,6) which would force you to write the production code that makes it pass while not breaking add(2,3) at the same time. You would end up with return x + y, but you wouldn't start with it. In theory. Naturally, Martin (or maybe it was someone else, I don't recall) likes to provide such examples for education, but doesn't expect you to actually write such trivial code that way. –  Anthony Pegram Mar 21 '13 at 0:47
    
@AnthonyPegram: Yes that makes sense. Of course pointing it out ruins the answer re: my OP. You wouldn't have written a test case that passed immediately. Would it be "wrong" to write TestAddMethod3 that Assert.IsTrue(Add(6,6) == 12);? –  Daniel Kaplan Mar 21 '13 at 0:58
1  
@tieTYT, generally, if I recall from Martin's book(s) correctly, the second test case would typically be enough to get you to write the general solution for a simple method (and, in reality, you would indeed just make it work the first time). No need for a third. –  Anthony Pegram Mar 21 '13 at 1:04
2  
@tieTYT, then you would keep writing tests until you did. :) –  Anthony Pegram Mar 21 '13 at 1:13
3  
There's a third possibility, and it goes against your example: you wrote a duplicate test. If you follow TDD "religiously", then a new test that passes is thus always a red flag. Following DRY, you should never write two tests that test essentially the same thing. –  congusbongus Mar 21 '13 at 1:25

Your test pass but you aren't wrong. I think, it happened because the production code is not TDD from the beginning.

Let's suppose canonical(?) TDD. There is no production code but a few test cases (that is of course always fail). We add production code to pass. Then stop here to add more fail test case. Again add production code to pass.

In other words, your test could be a kind of functionality test not a simple TDD unit test. Those are always valuable asset for the product quality.

I personally don't like such totalitarian, inhuman rules ;(

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.