Unit tests called multiple times?

Jesper jolsen1974 at gmail.com
Thu Oct 24 03:16:30 PDT 2013


On Friday, 12 April 2013 at 23:18:00 UTC, H. S. Teoh wrote:
> On Sat, Apr 13, 2013 at 01:08:38AM +0200, William wrote:
>> On Friday, 12 April 2013 at 23:01:55 UTC, Steven Schveighoffer
>> wrote:
>> >On Fri, 12 Apr 2013 18:52:50 -0400, William
>> ><squidkidsignup at gmail.com> wrote:
>> >
>> >>I'm compiling a medium-sized project written in D with the
>> >>-unittests flag.  I have some writeln statements in my unit
>> >>tests, for debug purposes, and I've noticed that certain unit
>> >>tests are being run more than once.  Sample output is along
>> >>these lines:
>> >>
>> >>DEBUG: unit test started...
>> >>DEBUG: loop found whatever
>> >>DEBUG: iteration successful
>> >>DEBUG: bar is equal to bar
>> >>DEBUG: unit test passed...
>> >>DEBUG: unit test started...
>> >>DEBUG: loop found whatever
>> >>DEBUG: iteration successful
>> >>DEBUG: bar is equal to bar
>> >>DEBUG: unit test passed...
>> >>DEBUG: unit test started...
>> >>DEBUG: loop found whatever
>> >>DEBUG: iteration successful
>> >>DEBUG: bar is equal to bar
>> >>DEBUG: unit test passed...
>> >>
>> >>is this standard behavior for DMD?  Is it documented 
>> >>anywhere?
>> >> It's not much of a problem, but it strikes me as rather odd,
>> >>and makes the debug output difficult to read.
>> >
>> >Are your unit tests inside templates?  If so, they are
>> >instantiated once per template.  To fix, move outside the
>> >template.
>> >
>> >This actually can be a nice feature, and at the same time
>> >horrible.  It's nice because you can parameterize your unit 
>> >tests!
>> >It's horrible because you have to be careful your unit tests 
>> >are
>> >valid for all possible instantiations!
>> >
>> >-Steve
>> 
>> Thank you!  That was exactly it.  I tend to put my unittests 
>> directly
>> after the functions/classes they test, so my opApply for an
>> implementation of n-dimensional associative arrays, (with
>> parameterized keys/values) was having its associated unittest 
>> called
>> every time the template was instantiated.  Moving it to the 
>> module
>> level fixed the problem, although now it reads as though the 
>> test is
>> intended to test the whole class, when in fact it only 
>> verifies the
>> correctness of opApply.  Still, feels good to have weird 
>> behavior
>> demystified.
>
> You could use static if to make the unittest only instantiate 
> for a
> particular template instance, e.g.:
>
> 	struct S(T) {
> 		...
> 		void method(T t) { ... }
>
> 		static if (T==int)
> 		unittest {
> 			auto s = S!int(123);
> 			s.method(123);
> 			assert( ... );
> 		}
> 	}
>
> This way, you can still keep unittests together with the 
> methods they
> test. Beware, though, that you actually instantiate S!int 
> somewhere
> outside, otherwise the unittest may never actually be 
> instantiated and
> run. :)
>
> (This does give rise to an interesting idiom of unittests 
> catered for
> specific types that only run when your code actually uses those
> particular instantiations. Hmm...)
>
>
> T

I have also noticed this, that unless you instantiate a class 
from a path from your main-function the unittest will not be run 
at all. Actually come to think of it I believe this also is valid 
for the very compilation of the code..no compilation of code if 
it's not instantiated, but does this only happen for 
template-classes?
I also have another problem with unittests, because my unittests 
would fail because exceptions was thrown and I would just get a 
completely useless message like:
rdmd -unittest c:\kode\datastructures\datastructures.d
DataStructures.ExceptionIndexOutOfBounds at c:\kode\datastructures\datastructures.d
(68): Index was out of bounds: 1 [2-3]
----------------
0x004155A8
0x00415433
0x0040294C
0x00408BA6
0x00411A48
0x0040BBE9
0x00408C48
0x765D336A in BaseThreadInitThunk
0x77119F72 in RtlInitializeExceptionChain
0x77119F45 in RtlInitializeExceptionChain

where 'ExceptionIndexOutOfBounds' is an exception I made myself 
and it is thrown when the unittests are run. The line-number 
given as a result points to the constructor of the 
'ExceptionIndexOutOfBounds'-exception and not to the unittest 
that failed.
The mem-addresses below I figure are supposed to be a stacktrace, 
but as you can see it lacks some basic information to make it 
useful.
Has anyone seen this before and what am I doing wrong? (or is 
this the designed behaviour?..i hope not).



More information about the Digitalmars-d mailing list