= Parameterized Unit Tests = Note: Dunit's parameterized testing features are a request for comments more than a final feature. While I believe that much of it is quite usable and reasonably reliable, trusting your company on it is only a slightly less risky proposition than betting everything on a lame horse. Most unit tests are example tests -- they give a specific example of correct input and require a specific example of correct output. However, unless the domain of the functions being tested is quite small, it is impractical to test exhaustively using example tests. In many cases, there is one specific property of the input that requires a specific corresponding property of the output. For instance, a name formatter might have the property that formatting a name for a person with a PhD must start with "Dr.". In this case, you can generate people who have PhDs automatically, and test each of them to make sure their formatted names start with "Dr.". Or in some cases, it is expensive to compute a result but cheap to check it. If you have a function that finds a Hamiltonian path in a graph, you can generate a random graph. Then, if the function returns a path, you can quickly ensure that the path is Hamiltonian. In cases like these, it is reasonable to check a result by calculation rather than manual precalculation. Dunit provides a provisional API for parameterized testing. == Marking a Parameterized Test == Parameterizing a test is merely adding a filter from dunit.param.filter: {{{ #!d class MyParameterizedTests : TestFixture { this () { tests["my parameterized test"] = sequential(generator1, generator2) = (int a, SomeStruct b) {}; tests["my combinatorial test"] = combinatorial(generator1, generator2) = (int a, SomeStruct b) {}; } } }}} "sequential" will execute the test method using the first value from each generator, then the second from each, then the third, and so forth. "combinatorial" will execute every possible combination of the parameters. For example, if the first generator yields [1, 2, 3] and the second yields ["hello", "world"], sequential will execute the test with (1, "hello") and (2, "world"). With the combinatorial filter, it will be run with (1, "hello"), (2, "hello"), (3, "hello"), (1, "world"), (2, "world"), and (3, "world"). The generators provided must implement dunit.param.model.Generator(T). Currently, the provided generators include an implementation for random integers, one for random floating point values, and one for integers in a given range. Writing a custom generator is reasonably easy; it must provide four methods: * reset For combinatorial tests; reset the generator to its original state. * hasMore Whether there is more data in the generator. * next Advance the generator to the next value. * current Get the current value. Good luck with your testing!