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:
Let us look at a simple example to understand this feature.
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:
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.
Here is the program output:
You can see that the test fails at line 20. Here is the failed 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:
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!
Recent Comments