UnitTest: unittest BlockStatement
Unit tests are a builtin framework of test cases applied to a module to determine if it is working properly. A D program can be run with unit tests enabled or disabled.
Unit tests are a special function defined like:
unittest { ...test code... }
Individual tests are specified in the unit test using AssertExpressions. Unlike AssertExpressions used elsewhere, the assert is not assumed to hold, and upon assert failure the program is still in a defined state.
There can be any number of unit test functions in a module, including within struct, union and class declarations. They are executed in lexical order.
Unit tests, when enabled, are run after all static initialization is complete and before the main()
function is called.
For example, given a class Sum
that is used to add two values, a unit test can be given:
class Sum { int add(int x, int y) { return x + y; } unittest { Sum sum = new Sum; assert(sum.add(3,4) == 7); assert(sum.add(-2,0) == -2); } }
When unit tests are enabled, the version identifier unittest
is predefined.
A unittest may be attributed with any of the global function attributes. Such unittests are useful in verifying the given attribute(s) on a template function:
void myFunc(T)(T[] data) { if (data.length > 2) data[0] = data[1]; } @safe nothrow unittest { auto arr = [1,2,3]; myFunc(arr); assert(arr == [2,2,3]); }
This unittest verifies that myFunc
contains only @safe
, nothrow
code. Although this can also be accomplished by attaching these attributes to myFunc
itself, that would prevent myFunc
from being instantiated with types T
that have @system
or throwing code in their opAssign
method, or other methods that myFunc
may call. The above idiom allows myFunc
to be instantiated with such types, yet at the same time verify that the @system
and throwing behavior is not introduced by the code within myFunc
itself.
{
and }
tokens to find the end of the UnitTest's BlockStatement. Documented unittests allow the developer to deliver code examples to the user, while at the same time automatically verifying that the examples are valid. This avoids the frequent problem of having outdated documentation for some piece of code.
If a declaration is followed by a documented unittest, the code in the unittest will be inserted in the example section of the declaration:
/// Math class class Math { /// add function static int add(int x, int y) { return x + y; } /// unittest { assert(add(2, 2) == 4); } } /// unittest { auto math = new Math(); auto result = math.add(2, 2); }
The above will generate the following documentation:
auto math = new Math; auto result = math.add(2, 2);
assert(add(2, 2) == 4);
A unittest which is not documented, or is marked as private will not be used to generate code samples.
There can be multiple documented unittests and they can appear in any order. They will be attached to the last non-unittest declaration:
/// add function int add(int x, int y) { return x + y; } /// code sample generated unittest { assert(add(1, 1) == 2); } /// code sample not generated because the unittest is private private unittest { assert(add(2, 2) == 4); } unittest { /// code sample not generated because the unittest isn't documented assert(add(3, 3) == 6); } /// code sample generated, even if it only includes comments (or is empty) unittest { /** assert(add(4, 4) == 8); */ }
The above will generate the following documentation:
assert(add(1, 1) == 2);
/** assert(add(4, 4) == 8); */
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/spec/unittest.html