Fog Creek Software
Discussion Board




Test Driven Design in Functional Languages

I understand how to use TDD packages when coding in an OO language, but I'm a bit confused on how one does this in a functional language.  I'm currently coding in TCL (project requirements) where the TCL is executed purely as a batch script. 

Is anyone aware of any TDD packages or practices for this type of coding?  Any experiences?

Lou
Thursday, December 04, 2003

Mike Scwern wrote test::More for Perl as well as test::Tutorial.

http://magnonel.guild.net/~schwern/talks/Test_Tutorial/Test-Tutorial.pdf

Basically, I'd suggest making a simple library with functions like this:

sub tests(int);
sub eq(string, int, int);
sub eq(string, bool, bool);
sub eq(string, double, double);
sub eq(string, string, string);
sub ok(string, bool);

The psuedo code looks something like this:

GLOBAL iTestNum int;
sub tests(i int)
{
  printf("1..%d\n", i);
  iTestNum = 1;
}

sub ok(s string, b bool)
{
  if (b)
  {
    print("ok %d - %s\n", iTestNum, s);
  }
  else
  {
    print("not ok %d - %s\n", iTestNum, s);
  }
  iTestNum++;
}

sub eq(s string, i int, i2 int)
{
  if (i==i2)
  {
    print("ok %d - %s\n", iTestNum, s);
  }
  else
  {
    print("not ok %d - %s\nGot %d\nExpected %d\n",
            iTestNum, s, i, i2);
  }
  iTestNum++;
}

//---End Psuedo Code

So your output to STDIO looks like this:

1..5
ok 1 - Foo with valid input
ok 2 - Foo with invalid group number
ok 3 - Error Message for invalid group number
not ok 4 - Foo with invalid date
not ok 5 - Error Message for invalid date
  Expected - "Date 10/35/2003 is not a valid date"
  Got - ""

Obviously, your function is something like:

func foo(iGroupNum int, sDate string) returns BOOL;

--All this is pseduo code you can write up in any langauge.

If you write it correctly, you can pump it through Test::Harness or Prove automatically.

That's the 5 minute version, anyway.  You can write test harnesses in any language.  (If you die after test 3 because of an unhandled exception, you know you SHOULD have had 5 tests because of the 1..5, so that too is a test.)



regards,

Matt H.
Thursday, December 04, 2003

Sorry to be picky, but TCL isn't a functional language.  Far from it.  Functional languages are those like Haskell, Clean and OCaml and the ML family.

David B. Wildgoose
Thursday, December 04, 2003

As Matt says, the principles are really no different. You just end up testing things like subroutine outputs (and side effects, where appropriate) instead of methods. Of course you can also test the entire script -- give it known inputs and check the outputs against expected outputs.

John C.
Thursday, December 04, 2003

Thanks for the ideas on how to strap the tests onto a language like TCL.  I think I have a pretty good handle on how I can proceed from here.

Lou
Thursday, December 04, 2003

When your code is written in a functional style, it's actually easier to set up tests.  The outputs for a chunk of code depend solely on the inputs, and don't depend on any calls before or after.  In an object-oriented style, you have to set up the internal states for the object(s), pass in any parameters, check the output of the call and then check the internal state for the object(s).  It takes more steps, and you may have to provide an unsafe "maintenance" interface to the object internals in order to test various failure conditions.

rwh
Thursday, December 04, 2003

Maybe the original poster meant "procedural" when he said "functional".

Exception guy
Thursday, December 04, 2003

I did.

Lou
Thursday, December 04, 2003

Good point, rwh, and that's something that's bugged me for a while about a lot of OO code I work with. For whatever reason I long ago got into a habit of writing my procedural code in a relatively functional, no-side-effects kind of way, which made it very natural to integrate lots of testing into the development process. But all the state that can get carried around in an OO world seems to get nasty sometimes, because it's much more difficult to be certain you've properly handled prerequisites and tested all possible states (though things like modeling processes around well-defined state machines does seem to help).

John C.
Thursday, December 04, 2003

Everyone here seems to have missed the fact that Tcl already comes with an extensive test-management package.  See documentation at http://www.tcl.tk/man/tcl8.4/TclCmd/tcltest.htm and background info at http://wiki.tcl.tk/1502 and http://wiki.tcl.tk/2604 .  You don't need to reinvent this wheel!

Colin Macleod
Friday, December 05, 2003


If you like JUNIT, there's even a TCLTKUnit:

http://park.ruru.ne.jp/ando/work/tclTkUnit/

I still think my 'output in test::harness format' thingy is a good idea. :-)

Matt H.
Monday, December 08, 2003

*  Recent Topics

*  Fog Creek Home