DCMTK now comes with an integrated test framework which allows you to run all the tests with a single command.
Running tests¶
Each module that provides test cases has a single binary in its /tests/
sub-directory to run these.
One can just execute this binary to run the whole test suite for that module.
Alternatively, it is possible to explicitely list the names of tests on the command line. For example, if you call ofstd's test program with the argument ofstd_OFString*
, all OFString-related tests will be executed.
The autoconf-based build system also provides a "check" Makefile-target which executes all tests. This means that make check
will execute all existing tests.
Writing new tests¶
Adding tests is easy. Just write the test-code and add it to the list of tests to be executed.
For example, the following will create a test named "ofstd_COUT_HelloWorld" which outputs a string:
#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/ofconsol.h"
#include "dcmtk/ofstd/oftest.h"
OFTEST(ofstd_COUT_HelloWorld)
{
COUT << "Hello world!" << OFendl;
}
Test names should start with the name of the module that the test belongs to followed by an underscore. If the test is for some specific class, e.g. OFString, this class name should follow. At the end there can be a short string describing the test.
Test names must be valid C++ identifiers. This means that e.g. spaces and dashes are not allowed.
When you are adding not only a new test but also a new file, this new file has to be added to Makefile.in and CMakeLists.txt. Without this, the new file wouldn't be compiled.
Tests may use oflog to generate additional messages. However, you should not use the INFO log level since this is used for displaying which test is currently executing. Also, messages on levels WARN, ERROR and FATAL might be better handled with OFCHECK_FAIL(). This leaves you with DEBUG and TRACE levels for own status messages.
Registering the new test¶
Each module has a file /tests/tests.cc
in which the list of tests resides. When writing a new test, you have to add your test to this list or it will be ignored:
[...]
OFTEST_REGISTER(ofstd_COUT_HelloWorld);
[...]
Running the new test¶
Now we have everything set up. We can now recompile everything and run the tests binary1:
$ ./tests -v ofstd_COUT_HelloWorld Running 1 tests for module 'ofstd': Running test 'ofstd_COUT_HelloWorld'... Hello world! Test results for module 'ofstd': 1 succeeded, 0 failed.
Testing conditions¶
We want to automatically determine if a test failed. This means that e.g. writing to the standard output is a bad idea. Instead, OFTest provides some macros which perform various checks:
OFCHECK¶
This macro evaluates its argument and causes the test to fail if the result is false. As a sample, let's check if math still works:
OFTEST(sample)
{
OFCHECK(2 < 1);
}
FAILED test 'sample' at tests.cc:40: 2 < 1
OFCHECK_EQUAL(a, b)¶
Consider a case like the following:
OFString a = "foo";
OFString b = "bar";
OFCHECK(a == b);
The resulting error message would just tell us that "a == b" failed which doesn't help us in figuring out the problem. We want to know the values that "a" and "b" have. For this purpose, the OFCHECK_EQUAL
-Macro exists. Its arguments must both be writable to OFOStringStream
with operator<<
.
OFString a = "foo";
OFString b = "bar";
OFCHECK_EQUAL(a, b);
FAILED test 'sample' at tests.cc:42: (foo) should equal (bar)
OFCHECK_FAIL(msg)¶
Sometimes we need more complex checks. Of course, we can do those with OFCHECK
, but that might result in unhelpful error messages. For this reason, there is OFCHECK_FAIL()
which sends its argument to a OFStringStream
. This macro will make the test unconditionally fail, so it's best to first check with an "if" for an error and then use this function for an error message.
OFCHECK_FAIL("Hi, the current time is " << time(NULL) << " and this test is failing");
FAILED test 'sample' at tests.cc:40: Hi, the current time is 1306322122 and this test is failing
1 With CMake, the tests binary is called <module name>_tests
, because CMake requires target names to be globally unique.