the Compartmented Robust Posix C++ Unit Test system |
|
---|
A test can fail by trapping an assertion, by leaving the test function body in an unexpected way, or by leaving files in the working directory. Normally, the expected way to leave the test body is to return from it, or run off the end. A few test modifiers can change that, however. Consider this simple class:
#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; };
Clearly the author of the class intended to differentiate
between unusual situations (a name doesn't exist when looking
it up,) and a programming error (a NULL pointer.) A test of the
class should reflect that and provoke both situations. The
exception can be tested using
ASSERT_THROW(expr, exc_type, matcher?)
,
but we can also use the
EXPECT_EXCEPTION(type)
modifier. The assert can likewise be tested with the
EXPECT_SIGNAL_DEATH(signo, action?)
modifier.
#include "symtable.hpp" #include <crpcut.hpp> TEST(insert_and_lookup) { symtable s; s.add("one", 1); s.add("two", 2); ASSERT_EQ(s.lookup("one"), 1); ASSERT_EQ(s.lookup("two"), 2); } 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); }
The NO_CORE_FILE
modifier prevents a trapped assertion from dumping core. After all,
we expect it to crash and the core dump would be unnecessary
clutter.
Running this test program with the
-v
/ --verbose
command line flag, yields:
PASSED!: insert_and_lookup =============================================================================== PASSED!: lookup_nonexisting =============================================================================== PASSED!: add_null stderr------------------------------------------------------------------------- symtable-test: samples/symtable.hpp:36: void symtable::add(const char*, int): Assertion `name' failed. =============================================================================== PASSED!: lookup_null stderr------------------------------------------------------------------------- symtable-test: samples/symtable.hpp:41: int symtable::lookup(const char*): Assertion `name' failed. =============================================================================== 4 test cases selected Sum Critical Non-critical PASSED : 4 4 0
Of course, had either of the tests lookup_nonexisting, add_null or lookup_null returned, the test would've failed.