Last update April 17, 2012

How To /
Unit Tests



D allows to write unit tests within a module source code. This makes it easy to write them while developing the module. An even better idea to write the tests before writing the module. This method is called Tests driven development.

Having unit tests within the module not only proves that the module has been tested, it gives good examples of how to use the module itself. So it has a documentation purpose. It also makes it easy to check for possible regressions after the module has been modified.

As an example, let's save in mytest.d the following code:

    module mytest;

/++ Whether or not $(D c) is in the ASCII character set - i.e. in the range 0..0x7F. +/ bool isASCII(dchar c) { return c <= 0x7F; }

unittest { foreach(dchar c; 0..128) assert(isASCII(c)); assert(!isASCII(128)); }

Compilation and run

This module has no main() function, so that it cannot be run by itself. If I compiles it with dmd, here is what I get:
    PS E:\DigitalMars\dmd2\samples> dmd mytest.d
    OPTLINK (R) for Win32  Release 8.00.12
    Copyright (C) Digital Mars 1989-2010  All rights reserved.
     http://www.digitalmars.com/ctg/optlink.html
    OPTLINK : Warning 23: No Stack
    OPTLINK : Warning 134: No Start Address
    PS E:\DigitalMars\dmd2\samples>

The linker is telling me I need to add a main() function to the module be able to compile this. Without a start address, the program simply cannot run. Appending the following line at the end of the file does the trick:
  void main(){}

Now, the compiler will run silently. But now, the main() function will be executed, and not my unit test ! In order to make sure the unit test is executed, one has to pass the -unittest switch to the compiler:
  dmd -unittest mytest.d

But I don't want to have to add a main() function in every module !

Well, there is an easy way to do this, use rdmd:

  rdmd -unittest --main mytest.d
Note the double minus signs: the -unittest switch is passed by rdmd to the dmd compiler, while --main is a rdmd switch. rdmd will silently add the missing main() function and run the test (make sure there is no main() in the file !). To verify that the test has been run, change the line
  assert(!isASCII(128));
into
  assert(isASCII(128));
You'll see that the test fails by throwing a core.exception.AssertError?


FrontPage | News | TestPage | MessageBoard | Search | Contributors | Folders | Index | Help | Preferences | Edit

Edit text of this page (date of last change: April 17, 2012 14:48 (diff))