5

Im researching TDD, I'm not really sure how to write a test before I have written production code. The problem is that TDD states that you make assertions and then write your code so that these assertions pass. But You have not created any classes yet (as part of the production code) so how are you meant to write the tests if you dont have any classes with which to assert.

Hope someone can explain....

4
  • Also what development environment are you using?
    – ChrisBD
    Dec 14, 2011 at 11:36
  • 1
    You could consider a test that fails to compile a failing test... </sarcasm> TDD's purpose is to help you, not to beat you over the head with regulations :) When @Ikke says interface, BTW, they mean public interface (class methods/properties), not a C# or Java interface. Dec 14, 2011 at 12:43
  • @MerlynMorgan-Graham Why the sarcasm? It is pretty standard in TDD to consider not compiling as a failing test. butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
    – Caleb
    Nov 16, 2015 at 23:39
  • I guess it's not so sarcastic after all. I must have felt snarky that day, even though looking back on it now I see nothing snarky. I've since then come across solutions involving use of the dynamic keyword and a factory function to return your class under test. This allows you to compile and run your test suite, even though methods or whole classes might be missing, and treat binding errors as runtime errors instead of compile time. This lets you write all the tests first, even before writing a single piece of code. There is a minor abstraction cost in your tests, so it is subject to taste. Nov 17, 2015 at 2:03

4 Answers 4

9

The first error that the test exposes is that using your API doesn't compile, because the class doesn't exist.

So you fix it so that the test compiles.

Then it will probably fail because the production code doesn't do what the test demands.

So you implement just enough of the class to make it pass.

Then you demand more sophisticated behaviour in your test.

Repeat again and again.

(Note: This is the orthodox, hardcore version of TDD. Opinions differ on whether it is really necessary to start with a deliberately uncompilable test, or how much business code to write between iterations. The extreme view is that more than 3-5 lines is always too much; others are more variable.)

4
  • Hi Kilian, so you always start with 1 test? Only some things I have read start with all your tests and then write your code to pass them all, but I guess this would never work?...
    – Pete2k
    Dec 14, 2011 at 11:40
  • That would be the ultra-hardcore version! Seriously, I have never heard of anyone advocating that you write the entire test suite first. It would defeat the point of small iterations! You only start out with a sizable test suite if you get it auto-generated from a very detailed machine-readable specification. Even then it's a horrible way to work because it takes forever to reach a green test bar, when the point of TDD is to "keep the bar green to keep the code clean!". Dec 14, 2011 at 14:13
  • 1
    Writing all the tests in advance isn't ultra orthodox. It's just plain wrong headed. Doing so means that you designed your code before the tests, which results in "test last" code. Remember, there test suite is a side benefit. The main idea is to design incrementally. Dec 14, 2011 at 17:32
  • I would add that with good refactoring support in your ide creating those missing classes and methods can be done quite easiliy and safely. Doing it this way focuses on the use and "what" of the code you are about to write instead of on the "how". Dec 15, 2011 at 9:35
2

You probably will start with a test that just instantiates a class. The compiler will emit an error because the class does not exist (red). To make the test succeed you have to create the class to test. The compiler will now run the test (green). Now you can, for example, call an nonexistent method. The compiler will complain (red). Create the method in the class, the compiler will stop complaining (green). Place an assertion in your test for the method. The test will fail (red). Extend the method such that the assertion works. The test will run (green).

2

Depending on what language and IDE you are using, you may have some support for "consume-first development".

e.g. in Visual Studio, you could write this line of code:

NewObjectThing foo = new NewObjectThing();

Now, you'll get the red squigglies to indicate that the type or namespace NewObjectThing cannot be found, and of course the code will not compile.

But if you right-click on it and select Generate -> Class, it will create a new file NewObjectThing.cs in the same folder & namespace as your current code, with an empty class declaration for NewObjectThing.

Similarly, if you then wrote:

foo.Name = "Fred";

..you could then right-click on Name and select Generate -> Property to add a property to the NewObjectThing class (and it would infer the type as string based on what you were assigning to it).

There are add-on tools like Resharper and CodeRush that add considerable flexibility and power to this process.

Anyway, have a look to see if your IDE supports something similar.

1

Another reason for writing a test before the code it's testing is written is to make sure the test fails. This ensures that you are actually calling the test and that it does fail. Sure, it's unlikely we would ever get that wrong, but .....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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