TDD: Should You Write Test First or Interface First?

ctddunit testing

I am learning TDD using c#, as far as I know test should drive the development, that is first write a failing test after write the bare minimum code to pass the test then do refactoring.

But it is also said that "Program to Interface, not Implementation", so write an interface first. This is where my confusion starts, If I am writing Interface first then it is violating two things

  1. The code that is written for interface is not driven by test.

  2. It is not the bare minimum obviously i can write it with a simple class.

Should I start by writing tests for interface also ? without any implementation what am I going to test ?

If this question sounds silly sorry for that, but I am utterly confused. May be I am taking things too literally.

Best Answer

Your first violation ("The code that is written for interface is not driven by test.") is not valid. Let's use a trivial example. Suppose you're writing a calculator class, and you're writing an addition operation. What test might you write?

public class CalculatorTest {
    @Test
    public void testAddTwoIntegers() {
        Calculator calc = new Calculator();
        int result = calc.add(2, 2)
        Assert.assertEquals(4, result);
    }
}

Your test has just defined the interface. It is the add method, see? add takes two arguments and returns their sum. You might later determine that you need multiple Calculators, and extract an (in this case) Java interface at that time. Your tests shouldn't change then, since you tested the public interface of that class.

At a more theoretical level, tests are the executable specification for a system. Interfaces to a system should be driven by the users of that system, and tests are the first method you have to define interactions.

I don't think you can separate interface design from test design. Defining interactions and designing tests for them are the same mental operation - when I send this information into an interface, I expect a certain result. When something is wrong with my input, I expect this error. You can do this design work on paper and then write your tests from that, or you can do them at the same time - it doesn't really matter.