Unit-testing – can’t make the unit test fail in “Red, Green, Refactor” of TDD

tddunit testing

So let's say that I have a test:

@Test
public void MoveY_MoveZero_DoesNotMove() {
    Point p = new Point(50.0, 50.0);
    p.MoveY(0.0);
    Assert.assertAreEqual(50.0, p.Y);
}

This test then causes me to create the class Point:

public class Point {
    double X; double Y;
    public void MoveY(double yDisplace) {
        throw new NotYetImplementedException();
    }
}

Ok. It fails. Good. Then I remove the exception and I get green. Great, but of course I need to test if it changes value. So I write a test that calls p.MoveY(10.0) and checks if p.Y is equal to 60.0. It fails, so then I change the function to look like so:

public void MoveY(double yDisplace) {
    Y += yDisplace;
}

Great, now I have green again and I can move on. I've tested not moving and moving in the positive direction, so naturally I should test a negative value. The only problem with this test is that if I wrote the test correctly, then it doesn't fail at first. That means that I didn't fit the principle of "Red, Green, Refactor."

Of course, This is a first-world problem of TDD, but getting a fail at first is helpful in that it shows that your test can fail. Otherwise this seemingly innocent test that is just passing for incorrect reasons could fail later because it was written wrong. That might not be a problem if it happened 5 minutes later, but what if it happens to the poor-sap that inheirited your code two years later. What he knows is that MoveY does not work with negative values because that is what the test is telling him. But, it really could work and just be a bug in the test.

I don't think that would happen in this particular case because the code sample is so simple, but if it were a large complicated system that might not be the case. It seems crazy to say that I want to fail my tests, but that is an important step in TDD, for good reasons.

Best Answer

Then don't write it.

You have already come to a point where you

  • Have the simplest code which passes all tests.
  • Are unable to think of edge-cases that aren't covered by the code.

Time to stop worrying about that method.

If you're writing tests for edge-cases that you know are already covered then you're worrying more about the test part of TDD than the design part. Unfortunately, this is not a very productive thing to do.

Why do you need to know that your method works with negatives? How far do you take that? Do you then test fractions? Do you test odd and even numbers? Each factor of ten? Every possible value of double?

If not then why test negatives? They're not going to act any differently from positives.

Related Topic