DSpec / Templates + Delegates
Fawzi Mohamed
fawzi at gmx.ch
Wed Mar 31 07:26:02 PDT 2010
As unittesting came up again I will use the occasion to pump up again
blip.rtest ;).
It is a randomized unittest framework.
see http://petermodzelewski.blogspot.com/2009/02/tango-conference-2008-rolling-dice.html
The basic idea is to make writing testing functions easy: you write
things that generate inputs for your testing functions (for example
file path, random strings, matrix/vector,...)
To add a structure or a class it is enough to implement
static MyType randomGenerate(Rand r)
or
static MyType randomGenerate(Rand r,ref bool acceptable)
or (if you have also a combinatorial, non random part)
static MyType randomGenerate(Rand r,int idx, ref int nEl, ref
bool acceptable)
For many types you already have predefined generators.
Then you write testing functions that use these arguments:
void myTestFunction(MyType arg1,int arg2,...){ ...}
and create test collections using autoInitTst.testNoFail,
autoInitTst.testFail, autoInitTst.testTrue, autoInitTst.testFalse (if
you have delegates, or the version with F at the end if you have
functions).
TestCollection myTests(TestCollection superColl=null){
TestCollection coll=new TestCollection("myCollection",
__LINE__,__FILE__,superColl);
autoInitTst.testNoFailF("myTest",
&myTestFunction,__LINE__,__FILE__,coll);
...
return coll;
}
and finally small tests can be run in a unittest setup, but for
something more serious run them with something like
import blip.rtest.RTest;
import dchem.test.AllTests: allTests;
import tango.math.random.Random;
import blip.io.Console;
version(NoTrace){} else { import
tango.core.stacktrace.TraceExceptions; import blip.util.TraceAll; }
void main(char[][] args){
serr(rand.toString());
serr("\n");
mainTestFun(args,allTests!()());
}
and this will call the function several times with automatically
generated inputs.
If a function has no arguments it is called just once, if it has only
combinatorial arguments then it is not called more often than it should.
Different tests run in parallel taking advantage of all the cpus you
have,and clearly you can write templatized testing functions.
Blip by default wants blas, lapack and hwlock libraries, but you can
compile it without using
-version=noHwlock -version=noBlas -version=noLapack
The parallel version stresses a little the thread/fibers and needs a
patched version of tango (with the latest reorganizations some bugs
crept back, so I use an old version by default, but I hope to submit
the patches for trunk soon). Sequential execution can be forced with -
version=SequentialWorkManager
Personally for serious tests I like to recreate the same structure as
the module structure, so that x.y.Z has its tests in x.test.y.ZTests ,
y will contain a collection called YTests that collects all the tests
of the modules in the package Y and finally all tests are collected in
the AllTests module.
These functions can even be templates, so that the compilation of the
library without tests is fast (my NArray tests are quite extensive and
need a bit to compile.
Then outside the library you have a test runner.
The test runner has command flags to initialize it with special values
(to reproduce a failure), or to ask the execution of a single test or
subsets.
Fawzi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100331/2880398c/attachment.html>
More information about the Digitalmars-d
mailing list