Alex Rivera | Logout

How to use TDD correctly to implement a numerical method?

Asked 2009-09-23T02:09:16.123
13

I am trying to use Test Driven Development to implement my signal processing library. But I have a little doubt: Assume I am trying to implement a sine method (I'm not):

  1. Write the test (pseudo-code)

    assertEqual(0, sine(0))
    
  2. Write the first implementation

    function sine(radians)
        return 0
    
  3. Second test

    assertEqual(1, sine(pi))
    

At this point, should I:

  1. implement a smart code that will work for pi and other values, or
  2. implement the dumbest code that will work only for 0 and pi?

If you choose the second option, when can I jump to the first option? I will have to do it eventually...

Edit
Report

2 Answers

10

At this point, should I:

  1. implement real code that will work outside the two simple tests?

  2. implement more dumbest code that will work only for the two simple tests?

Neither. I'm not sure where you got the "write just one test at a time" approach from, but it sure is a slow way to go.

The point is to write clear tests and use that clear testing to design your program.

So, write enough tests to actually validate a sine function. Two tests are clearly inadequate.

In the case of a continuous function, you have to provide a table of known good values eventually. Why wait?

However, testing continuous functions has some problems. You can't follow a dumb TDD procedure.

You can't test all floating-point values between 0 and 2*pi. You can't test a few random values.

In the case of continuous functions, a "strict, unthinking TDD" doesn't work. The issue here is that you know your sine function implementation will be based on a bunch of symmetries. You have to test based on those symmetry rules you're using. Bugs hide in cracks and corners. Edge cases and corner cases are part of the implementation and if you unthinkingly follow TDD you can't test that.

However, for continuous functions, you must test the edge and corner cases of the implementation.

This doesn't mean TDD is broken or inadequate. It says that slavish devotion to a "test first" can't work without some thinking about what you real goal is.

answered 2009-09-23T02:26:50.807
2

Note that (in NUnit) you can also do

Assert.That(2.1 + 1.2, Is.EqualTo(3.3).Within(0.0005);

when you're dealing with floating-point equality.

One piece of advice I remember reading was to try to refactor out the magic numbers from your implementations.

answered 2009-09-23T02:21:53.187

Your Answer