Support for Unit Testing in D Language

Written by on February 6, 2022 in D Language, Programming with 0 Comments

While I admire D language for many of its elegant and powerful features, two features stand out in my opinion. These are support for Design by Contract (DBC) and Unit Testing. I am a great fan of DBC and will cover that feature in a future article. Today I let me briefly touch upon D‘s support for Unit Testing.

Unit tests in D language are defined in blocks of code like this:

unittest {

/* code to test */

}

Where do we define such unit tests? Well, we can define them at many convenient points:

  • Within struct, union, class
  • Outside of any code block
  • In a separate file, independent of any other code

The important point to note is that they are executed after all static initialization takes place, but before “main” gets control. If there are many unit test blocks in the same file, they are executed in lexical order.

What can we have inside a unittest block? Any valid D code is acceptable. In a majority of cases, though, we use different forms of “assert”:

  • assert(<condition>)
  • assertThrown(<expression>) 
  • assertNotThrown(<expression>)

Both assertThrown and assertNotThrown can optionally be used with specific template parameters, depending on the need.

It is possible to associate attributes such as @safe, @nogc, etc. It is even allowed to tag them as “private” (useful in the context of automatic documentation).

For the complete specification of unit tests in D language, go through this documentation.

Next, how do we enable the unit tests? The commandline flag “-unittest” needs to be passed to the DMD compiler to compile and run unit tests.

I use “VisualD” (on top of Visual Studio 2017) for running D programs. Here is how to set the corresponding flag in the IDE:

Enabling "unittest"

Enabling “unittest”

Let us look at a simple example to understand this feature.

Example D Program

Example D Program

In my VisualD environment, when I enable the “unittest” flag, the above program compiles and when I run it, this is the output I get:

Unittest Output

Unittest Output

What is interesting is that the actual “main” does not run, but only the unit tests run (even though all the tests pass). Let me now deliberately introduce a bug in the “factorial” function and then run the tests again.

Buggy Function

Buggy Function

Here is the program output:

Failed Tests

Failed Test

You can see that the test fails at line 20. Here is the failed case:

Failed Test Case

Failed Test Case

When the program is “correct” (as per the unit tests), in order to get the actual “main” to run, I have to remove “unittest” from the commandline argument. When I do that, here is the program output:

Program Output

Program Output

I hope this gives you an idea of the power of “unittest” blocks in D language. If you are into Test Driven Development, I am sure you will find this feature immensely useful. Do not forget to go through the official documentation to learn more about this feature.

Have a nice weekend!

Tags: ,

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published.

Top