jmrah
jmrah

Reputation: 6221

Confused on how to write tests for classes that are refactored to compose other classes

I haven't read widely or thoroughly on TDD, but I feel like I do know the basics.

One point of TDD is that you write the tests first. In the case of a Calculator program, perhaps one test case looks like this:

public class CalculatorTest {
    public void shouldSumOneAndOneCorrectly() {
        Calculator calc = new Calculator();
        calc.push(new Number(1));
        calc.push(new SumOperator());
        calc.push(new Number(1));
        Number sum = calc.equals();
        assert(sum.equals(new Number(2)));
    }
}

If I write the above test before writing any implementation, then I'm faced with this problem: Am I testing if the Calculator class sums correctly, or should I be testing that the Number class sums correctly? Of course, this is assuming that the Calculator class would be calling a number.add(number) function in its implementation somewhere. But I thought you shouldn't be thinking about implementation when you are writing your tests first?

If I start writing tests for a Calculator class, and then during the implementation, realize that my Calculator class simply delegates and coordinates to composed objects, do I then write tests for those composed objects? Do I keep the Calculator tests?

Do you start writing tests at a very high level (Calculator) and then as you implement functionality and create composed classes, write more tests for those classes?

I hope I'm making some sense.

Upvotes: 0

Views: 170

Answers (1)

Sam Holder
Sam Holder

Reputation: 32946

I would start with focusing on the behaviour.

You want your Calculator class to be able to add 2 numbers. Its (pretty) irrelevant if you do this via some other class as that is an implementation detail of the calculator. Your tests should give you coverage of the Number class if you implement the functionality there.

If you decide that the functionality of the Number class is something which is generically useful outside of the Calculator (and is no longer an implementation detail) then that is the point at which I would consider writing behaviour based tests for the Number class separately, but before that point I would rely on the tests of the Calculator behaviour.

For me this is analogous to tests for a public method which delegates to private methods to get the job done. You don't want to write tests for the private methods as they should be covered by the tests for the behaviour of the public methods.

Upvotes: 2

Related Questions