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.)