A cool thing I learned on the way to d2.

unittests can be templatized just like the classes/structs they reside in. When enhancing dcollections with lots of detailed unit tests, I was doing things like this:

class ArrayList(V)
{
   V take() {...}
   unittest
   {
      auto al = new ArrayList!uint;
      al.add([0u, 1, 2, 3, 4]);
      assert(al.take() == 4);
      assert(al.length == 4);
   }
}

But I found that the unittests weren't compiling -- at all! What I realized is that unittests are part of the instantiation!

At first, I was peeved, I wanted to simply test the "take" function not caring what type I used to instantiate the class with. In order to do that, I have to move all the unit tests outside the class declaration -- not good for maintainability.

But I came to realize -- there is great power in that feature. For example, with a little change to my unit test:

unittest
{
   auto al = new ArrayList;
   al.add([cast(V)0, 1, 2, 3, 4]);
   assert(al.take() == 4);
   assert(al.length == 4);
}

I can create a global unit test that looks like this:

unittest
{
  ArrayList!uint al1;
  ArrayList!int al2;
  ArrayList!ulong al3;
  ArrayList!long al4;
}

and now my unit tests cover 4 instantiations. With a single line, I can extend my unittest coverage to another type!

Of course, the issue is, how do I write a truly generic unit test? For example, that 'take' unit test fails for ArrayList!string. If I wanted to compile a project that happened to include the string instantiation with unit tests turned on, it fails to compile.

The ugly solution is to use static if like so:

static if(isIntegral!V)
{
   unittest
   {
   }
}

But that is, well, ugly.  I thought of proposing something like:

unittest if(isIntegral!V)
{
}

which looks better, but still is a bit verbose. This might be the cleanest solution. Any suggestions?

I still would like a way to do a unittest inside a template that is technically not part of the instantiation. This allows you to unit test a function with a specific instantiation when it's not easy to build a generic unit test *and* you want the unit test close to the function declaration. Although it's bloaty, you could just write your unittests like I did originally, specifying the full type in the unit test, but you then have to remember to create an external unit test to do the instantiation.

I hate to suggest static unittest :P  Any other ideas?

-Steve

Reply via email to