Joshua Harris
Joshua Harris

Reputation: 283

What to do when TDD tests reveal new functionality that is needed that also needs tests?

[EDIT]: Click here for the question on the appropriate site.

What do you do when you are writing a test and you get to the point where you need to make the test pass and you realize that you need an additional piece of functionality that should be seperated into it's own function? That new function needs to be tested as well, but the TDD cycle says to Make a test fail, make it pass then refactor. If I am on the step where I am trying to make my test pass I'm not supposed to go off and start another failing test to test the new functionality that I need to implement.

For example, I am writing a point class that has a function WillCollideWith(LineSegment):

public class Point {
    // Point data and constructor ...

    public bool CollidesWithLine(LineSegment lineSegment) {
        Vector PointEndOfMovement = new Vector(Position.X + Velocity.X,
                                               Position.Y + Velocity.Y);
        LineSegment pointPath = new LineSegment(Position, PointEndOfMovement);
        if (lineSegment.Intersects(pointPath)) return true;
        return false;
    }
}

I was writing a test for CollidesWithLine when I realized that I would need a LineSegment.Intersects(LineSegment) function. But, should I just stop what I am doing on my test cycle to go create this new functionality? That seems to break the "Red, Green, Refactor" principle.

Should I just write the code that detects that lineSegments Intersect inside of the CollidesWithLine function and refactor it after it is working? That would work in this case since I can access the data from LineSegment, but what about in cases where that kind of data is private?

Upvotes: 3

Views: 140

Answers (3)

bryanbcook
bryanbcook

Reputation: 18288

If you follow TDD to the letter as per how Kent Beck defines it in his book, when you come across something that you will also need to test, make a note of it on a piece of paper (he refers to this as a test list) and then focus on the current test. Kent suggests you should work on one test at a time.

From a test first perspective you should focus on making the test pass, which has several options:

  1. Write the implementation of Intersects inline in the current method. "Green" means working, not pretty. Once working, refactor both the code AND tests.

  2. Stub it out. Pass in a test double (mock) into the method that can simulate the contract.

  3. Fake it. When you come across a method you need, make a note for other tests, then write a basic implementation (eg "return true")

Upvotes: 2

Bradley Thomas
Bradley Thomas

Reputation: 4097

I suggest your best option is to mock it, that way you stay in your workflow and you also test a limited amount of code at a time.

Upvotes: 1

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236268

I like to use [Ignore] attribute to mark tests which require attention (e.g. when it is not completed). Such tests will not run. Ignored tests are highlighted in test-runners (usually yellow or orange). Even if all other tests are passed, you will not see green line while there any ignored tests. This insures that tests will not be forgotten.

Upvotes: 0

Related Questions