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