Forget about TDD for a moment. How would you think about testing if you started with an interface or class first? Here's what I'd do: Start with my class Foo.
public class Foo {
private String message;
public Foo(String m) { this.message = m; }
public String getMessage() { return this.message; }
public static int add(int x, int y) { return x*y; }
}
Then I'd write a JUnit test for it:
public class FooTest {
@Test
public void testConstructor() {
String expected = "Hello";
Foo f = new Foo(expected);
Assert.assertEquals(expected, f.getMessage());
}
@Test
public void testAdd() {
int expected = 5;
Assert.assertEquals(expected, Foo.add(2, 3));
}
}
I'd run this test and immediately figure out that I had a problem with that add implementation.
So what does TDD do? They take things to the extreme: write the test first, then write the class. You try to compile the test and it fails because you didn't write the class. Once you have a class implementation, you maintain a tight loop of code-test for every method, maintaining 100% passing and good coverage including happy path, error conditions, and edge cases.
TDD doesn't mean you have no idea about the class you're going to write and test. You should have some idea of the API you need before you start.
Personally, I think demanding that you write the test before the class is silly. Sketch out the class, just don't go too far before you test it. Write a method, test it, write another.
By the way: If you write a JUnit test without an Assert
in it you're doing it wrong. Don't write to System.out
. The pass or fail judgment should not depend on your visual inspection; it should be asserted and determined automatically.