[Haskell-cafe] Type System vs Test Driven Development

Arnaud Bailly arnaud.oqube at gmail.com
Thu Jan 6 08:55:24 CET 2011


I would supplement this excellent list of advices with an emphasis on
the first one: Test-Driven Development is *not* testing, TDD is a
*design* process. Like you said, it is a discipline of thought that
forces you first to express your intent with a test, second to write
the simplest thing that can possibly succeed, third to remove
duplication and refactor your code.

It happens that this process is somewhat different in Haskell than in
say Java, and actually much more fun and interesting thanks to the
high signal-to-noise ratio syntax of Haskell (once you get acquainted
with it of course) and its excellent support for abstaction,
duplication removal, generalization and more generally refactoring
(tool support may be better though...). For example, if I were to
develop map in TDD (which I did actually...), I could start with the
following unit test:

> map id  [] ~?= []

which I would make pass very simply by copy and pasting, only changing
one symbol.

> map id  [] = []

Then I would add a failing test case:

> TestList [ map id  [] ~?= [] , map id [1] ~?= [1] ]

which I would make pass with, once again simple copy-pasting:

> map id  []   = []
> map id  [1] = [1]

Next test could be :

> TestList [ map id  [] ~?= [] , map id [1] ~?= [1], , map id [2] ~?= [2] ]

Which of course would pass with:

> map id  []   = []
> map id  [1] = [1]
> map id  [2] = [2]

then I would notice an opportunity for refactoring:

> map id  []   = []
> map id  [x] = [x]

etc, etc...Sound silly? Sure it is at first sight, and any
self-respecting haskeller would write such a piece, just like you
said, without feeling the need to write the tests, simply by stating
the equations about map.

The nice thing with haskell is that it has a few features that helps
in making those bigger steps in TDD, whereas less gifted languages and
platforms requires a lot more experience and self-confidence to "start
running":
 - writing types delivers some of the design burden off the tests,
while keeping their intent (being executable instead of laying in dead
trees),
 - quickcheck and friends help you express a whole class of those unit
tests in one invariant expression, while keeping the spirit of TDD as
one can use the counter-examples produced to drive the code-writing
process.

<plug>
Some people might be interested in
http://www.oqube.net/projects/beyond-tdd/ (a session I co-presented at
SPA2009) which was an experiment to try bringing the benefits of TDD
with quickcheck in haskell to the java world.
</plug>

Regards,
Arnaud

PS: On



More information about the Haskell-Cafe mailing list