Introduction
Minitest is library to help with unit testing. It provides very small set of features (one macro, two functions):
- macro (
MINITEST
) to define a test
- execute all tests, in random order (to uncover possible dependencies between the tests)
- execute only tests from last modified source files (to shorten the edit - compile - test cycle)
Example of use:
#include <minitest.hpp>
#include <assert.h>
#ifndef NDEBUG
MINITEST
{
assert(...);
}
MINITEST
{
...
assert(...);
assert(...);
}
#endif
int main()
{
minitest::execute_all_tests();
}
The tests could be put in many translation units (*.cpp files).
Background
There are quite a few of C++ test frameworks (for overview see e.g. here). The library presented here doesn't offer as many features as others with hope it will be useable without much of learning and will be modifiable easily.
The library could be used when adding *.cpp files of large framework is not possible, as first step in creating battery of tests before going with large framework or to create second, independent set of tests for an application.
Using the code
Create test case:
#include <minitest.hpp>
#ifdef DO_TESTING
MINITEST
{
AClass object;
}
MINITEST
{
if (pDatabase) {
pDatabase->do_internal_test();
} else {
assert(false);
}
}
#endif
There's only one macro - definition of test. To do actual checking use assert()
or debug tools of your preference.
Execute all tests:
Function minitest::execute_all_tests(bool)
runs the tests in random or fixed order and returns information how many tests passed and details about possible faulty one (for details see structure minitest::result
in header).
#include <iostream>
#include <minitest.hpp>
int main()
{
minitest::execute_all_tests();
minitest::execute_all_tests(false);
minitest::result res = minitest::execute_all_tests();
if (res.all_tests_succeeded)
{
std::cout << "All " << res.sucessful_tests_count << " tests OK.\n";
}
else
{
std::cout << "Only first " << res.sucessful_tests_count << " test(s) OK\n"
<< "The test in file " << res.failed_test_file << ", line "
<< res.failed_test_line << " threw an exception.\n";
res.failed_test();
}
}
Random order of execution:
rand()
is used (internally by std::random_shuffle()
) to simulate randomness of testing. In order to repeat the same sequence of tests do one of following
- call
minitest::execute_all_tests(false)
and no randomization will be done - last order of execution is preserved
- set and remember seed for random generator (by
srand()
) and set it again when needed
Execute only tests from last changed sources:
If running the test takes too long you may wish to run just those that were affected by recent changes in source code. The library provides support for this:
#include <minitest.hpp>
int main()
{
minitest::result res = minitest::test_last_changed_files(3);
if (res.all_tests_succeeded) {
}
}
The library checks timestamp of all source files, selects the N files modified last and executes only tests from these. This should help to speed up edit-compile-test cycle and keep one in flow.
However running all the tests should be done from time to time: dependecies between modules are not handled here!
Dealing with DLLs:
Calling minitest::execute_all_functions()
in main()
will not run tests in DLLs. You need to add helper function, like:
// pseudocode
void complete_app_test()
{
minitest::execute_all_tests(); // in main executable
foreach( just_loaded_DLLs ) {
invoke_execute_all_tests( a_dll );
}
}
int main()
{
complete_app_test();
}
This nuisance is due to header-only implementation of the library.
Dependencies and portability
STL is required. The library uses couple of headers from
Boost. If needed, these headers can be replaced with short hand-coded equivalent.
The library was tested with VC6, BCB6 and Intel C++. I expect it to work under Posix systems as well.
History
- March 2nd, 2005: version 1.0 submitted