26

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.

3
  • 8
    "Program to an interface" means separating what you need from a piece of code from how it gets done. It doesn't mean to literally use an interface for everything. A class also provides an interface, because you can hide implementation details in private variables.
    – Doval
    Oct 16, 2014 at 18:11
  • @Doval, Yes, you don't need an interface for everything, just what's called a contract. This could be in the form of an abstract class, for example, though it shouldn't be a virtual class/method because you shouldn't be able to instantiate it.
    – trysis
    Oct 17, 2014 at 5:09
  • 2
    TDD says, "write a test that fails." Some strict TDDers say that it counts as a "fail" if you can't compile the test because the data type on which it operates has not yet been declared. Dec 22, 2015 at 14:39

6 Answers 6

31

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.

4
  • 2
    +1 "I don't think you can separate interface design from test design" should be in bold, IMHO :) Oct 28, 2014 at 12:30
  • It's even easier to show, if you want to tests more than one implementation of a functionnality, says an XML Import and a CSV Import, you can tests them with exactly the same method from the same interface though the implementation will change. Furthermore, tests involve often some mocking, and for this interface are necessaries.
    – Walfrat
    Mar 21, 2016 at 15:46
  • You say the test doesn't need to change, but new Calculator() is the implementation right ? If there's a new implementation needed, maybe you'd do a MultiplicationCalculator then, and you'd need to change the test to use new AdditionCalculator() for it to still pass ? Or am I missing something ? Sep 19, 2016 at 11:33
  • 3
    @SteveChamaillard Sure, if your design has you change the class name from Calculator to AdditionCalculator the test would have to change to match. Of course, by doing TDD what would actually happen is you would change the test first, and the class change would follow in order to make the test pass.
    – Eric King
    Sep 19, 2016 at 14:56
6

What are we doing when we write an interface? Are we writing code, or are we designing?

I'm not a fan of the notion of Test Driven Design, but I love Test Driven Development. Personally, I've gotten my best results when I design the class up front by designing the interface before I write a test. I don't count the interface as code. The interface is a design that I will be implementing using TDD. Its likely to change an evolve as I work, but it is my roadmap (along with my test list).

I'll stop before I start to rant, but hopefully that's a helpful way for you to think about it.

4

In TDD should I have to write Test first or Interface first?

It all depends on how orthodox / religious you want to do TDD.

I am learning TDD

Since you are learning, you should experiment to get a personal workflow, which works for you.

  1. If you want to do it according to the books, you write at first a test, which obviously will fail, because you are starting with no code at all. Then you write some code to make the test pass. If that is done, you are free to refactor the existing code, since you have a test which provides some kind of safety-net for refactorings. Deciding to use an Interface is some kind of refactoring.

  2. Besides TDD or not: The question, whether to use an interface or not isn't interesting in the first place. Of course if you are sure, you have different behaviour you want to spread across several objects, it makes sense to think about using an Interface: For example, if you have some kind of output to different destinations, it makes sense to implement it via an interface Writer and have different classes for the output (FileWriter, Printer etc.). Although it is a common saying to write to an interface, but that doesn't mean: use an interface for everything. Sometimes it is one level of indirection to much. Btw. the same goes for services. But that's a different topic.

  3. On the other hand, you could develop test driven in another way: design your code for testability. Which means, you write code, which is easy to test - although you write the tests afterwards. It doesn't matter if you write tests beforehand or afterwards, as long as you test anyways.

2
  • 5
    Can't agree with the last point "It doesn't matter if you write tests beforehand or afterwards, as long as you test anyways". If you happen to write the test afterwards you can't be sure whether the test is testing the right thing. Oct 16, 2014 at 19:08
  • 4
    As I said ... It depends on how orthodox you are ... Oct 16, 2014 at 20:02
2

TDD or BDD would mean Doing your domain interfaces first and then writing tests against them by my interpretation. an interface's implementation has an expected behavior.

it's still test before code because an interface contains no testable logic it is the structure you write a test against.

I Would Do it as follows

  1. Write the Semi Formal Behavior (Given:When:Then:)

  2. Write the Interface (to host behavior encapsulating method)

  3. Write the Test it Identifies (input the given, call the when, test the then)

  4. Write/Alter the Concrete (Class that implements the interface) to Pass the Test

0

Never write tests before you've designed the interfaces. When you are thinking about what kinds of tests to write (test design) you should not also be simultaneously designing (architecting) your application. Don't think about two things at the same time. Have you heard of separation of concerns? It applies not just to the physical structure of your code but also to your thinking process.

Decide how your application should be designed first. This means that you design your interfaces and the relationships between these interfaces. Until you've done this you should not start thinking about tests. Once you know what your interfaces are then you can either first creatw them and then write tests against them or write tests first and then create them. In the latter case obviously you won't be able to compile the tests. I see no harm nor any violation of TDD philosophy in creating the interfaces before the tests.

4
  • reasoning in top answer looks more compelling: "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..."
    – gnat
    Mar 21, 2016 at 16:26
  • @gnat I believe Nissam here is referring to the C# interface keyword, not the general term "interface".
    – RubberDuck
    Mar 22, 2016 at 6:20
  • @RubberDuck I also think so and I believe this is a poor approach. "Until you've done this you should not start thinking about tests..." As I wrote, reasoning in top answer looks more compelling, both in general sense of interface and in the sense of concrete keyword
    – gnat
    Mar 22, 2016 at 6:53
  • Fair enough @gnat that wasn't clear from your comment. Personally, I agree with Nissam here. I find it stops people from using TDD as an excuse not to design at all. YMMV.
    – RubberDuck
    Mar 22, 2016 at 7:12
-2

Its okay to write the interface/code/test at the same time as long as their incorporation into the project is atomic.

Unless your boss is religious about TDD, in which case you probably have to write empty interface -> test -> minimal code (pointless step) -> more tests -> more pointless code -> more tests -> finally write the real code -> done.

Not the answer you're looking for? Browse other questions tagged or ask your own question.