...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Any unexpected/uncaught exception raised in the test case body will be intercepted
by the Boost.test framework and will result in the termination of the test-case
with the status failed
.
Code |
---|
#define BOOST_TEST_MODULE example #include <boost/test/included/unit_test.hpp> struct my_struct { my_struct(int var_) : var(var_) { if(var_ < 0) throw std::runtime_error("negative value not allowed"); } int var; }; BOOST_AUTO_TEST_CASE( test ) { my_struct instance(-2); // ... } BOOST_AUTO_TEST_CASE( test2 ) { BOOST_TEST(true); } |
Output |
---|
> example --log_level=all Running 2 test cases... Entering test module "example" test.cpp:20: Entering test case "test" unknown location:0: fatal error: in "test": std::runtime_error: negative value not allowed test.cpp:20: last checkpoint: "test" entry. test.cpp:20: Leaving test case "test"; testing time: 247us test.cpp:26: Entering test case "test2" test.cpp:28: info: check true has passed test.cpp:26: Leaving test case "test2"; testing time: 103us Leaving test module "example"; testing time: 492us *** 1 failure is detected in the test module "example" |
More control over the exception correctness is often required, for instance to test that an expression is raising a specific exception, intentionally.
The Unit Test Framework provides several assertions for testing a code with respect to the exceptions correctness. The following assertions are available:
BOOST_<level>_NO_THROW
checks that no exception
is raised from an expression,
BOOST_<level>_THROW
checks that an expression
raises an exception of a specific type
BOOST_<level>_EXCEPTION
checks that an expression
raises an exception of a specific type, a passes the exception instance
to a predicate function for further validation (introspection for instance)
The following example demonstrate how to use these tools to test the correct
behavior of the API of FileWordHistogram
,
in the constructor and the preconditions of the member function.
Code |
---|
#define BOOST_TEST_MODULE example #include <boost/test/included/unit_test.hpp> #include <stdexcept> #include <fstream> //! Computes the histogram of the words in a text file class FileWordHistogram { public: //!@throw std::exception if the file does not exist FileWordHistogram(std::string filename) : is_processed(false), fileStream_(filename) { if(!fileStream_.is_open()) throw std::runtime_error("Cannot open the file"); } //! @returns true on success, false otherwise bool process() { if(is_processed) return true; // ... is_processed = true; return true; } //!@pre process has been called with status success //!@throw std::logic_error if preconditions not met std::map<std::string, std::size_t> result() const { if(!is_processed) throw std::runtime_error("\"process\" has not been called or was not successful"); return histogram; } private: bool is_processed; std::ifstream fileStream_; std::map<std::string, std::size_t> histogram; }; BOOST_AUTO_TEST_CASE( test_throw_behaviour ) { // __FILE__ is accessible, no exception expected BOOST_REQUIRE_NO_THROW( FileWordHistogram(__FILE__) ); // ".. __FILE__" does not exist, API says std::exception, and implementation // raises std::runtime_error child of std::exception BOOST_CHECK_THROW( FileWordHistogram(".." __FILE__), std::exception ); { FileWordHistogram instance(__FILE__); // api says "std::logic_error", implementation is wrong. // std::runtime_error not a child of std::logic_error, not intercepted // here. BOOST_CHECK_THROW(instance.result(), std::logic_error); } } |
Output |
---|
> example --log_level=all Running 1 test case... Entering test module "example" test.cpp:47: Entering test case "test_throw_behaviour" test.cpp:50: info: check 'no exceptions thrown by FileWordHistogram("test")' has passed test.cpp:54: info: check 'exception std::exception is caught' has passed unknown location:0: fatal error: in "test_throw_behaviour": std::runtime_error: "process" has not been called or was not successful test.cpp:62: last checkpoint test.cpp:47: Leaving test case "test_throw_behaviour"; testing time: 533us Leaving test module "example"; testing time: 643us *** 1 failure is detected in the test module "example" |
Note | |
---|---|
An |
Publications
Standard C++ Foundation