| the Compartmented Robust Posix C++ Unit Test system | hosted by |
|---|
It is often a good idea to group tests that verify similar parts of the functionality into testsuites. In crpcut a testsuite is a list of tests and enclosed testsuites. At the out most level, tests are included in the unnamed testsuite.
Testsuites are declared using the
TESTSUITE(name, ...)
macro. A testsuite is a C++ namespace with some
decorations attached. For example it is possible to express
dependencies on testsuites (i.e. the requirement that all tests
in a testsuite pass,) and it is possible for testsuites to depend
on tests and other testsuites.
![]() | Tip |
|---|---|
| Experience has shown that it is a good idea to let testsuites depend on testsuites, and tests in testsuites depend on other tests in the same testsuite |
Consider the simple symtable class from earlier:
#include <map>
#include <string>
#include <cassert>
class symtable
{
public:
void add(const char *name, int val)
{
assert(name);
table[name] = val;
}
int lookup(const char *name)
{
assert(name);
return table.at(name);
}
private:
std::map<std::string, int> table;
};
The following longish test program follows the recommended form for testsuites with dependencies:
#include "symtable.hpp"
#include <crpcut.hpp>
TESTSUITE(construct_and_destroy)
{
TEST(construct)
{
(void)new symtable; // intentional leak
}
TEST(destroy, DEPENDS_ON(construct))
{
symtable s;
}
}
TESTSUITE(normal_access, DEPENDS_ON(ALL_TESTS(construct_and_destroy)))
{
TEST(insert_one)
{
symtable s;
s.add("one", 1);
}
TEST(insert_several, DEPENDS_ON(insert_one))
{
symtable s;
s.add("one", 1);
s.add("two", 2);
s.add("three", 3);
}
TEST(lookup, DEPENDS_ON(insert_several))
{
symtable s;
s.add("one", 1);
s.add("two", 2);
int v = s.lookup("one");
ASSERT_EQ(v, 1);
v = s.lookup("two");
ASSERT_EQ(v, 2);
}
}
TESTSUITE(abnormal, DEPENDS_ON(ALL_TESTS(normal_access)))
{
TEST(lookup_nonexisting, EXPECT_EXCEPTION(std::out_of_range))
{
symtable s;
s.add("one", 1);
s.lookup("two");
}
TEST(add_null, EXPECT_SIGNAL_DEATH(SIGABRT), NO_CORE_FILE)
{
symtable s;
s.add(0, 1);
}
TEST(lookup_null, EXPECT_SIGNAL_DEATH(SIGABRT), NO_CORE_FILE)
{
symtable s;
s.add("one", 1);
s.lookup(0);
}
}
int main(int argc, char *argv[])
{
return crpcut::run(argc, argv);
}
Testsuites are also useful when there is a desire to run a
subset of the tests. Running the above test program with
-v
-n
"normal_access" yields:
PASSED: normal_access::insert_one
===============================================================================
PASSED: normal_access::insert_several
===============================================================================
PASSED: normal_access::lookup
===============================================================================
Total 3 test cases selected
UNTESTED : 0
PASSED : 3
FAILED : 0
(the -n command
line flag tells crpcut to ignore dependencies, and
the -v command line
flag makes crpcut list also the tests that succeeds.)