Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

Exception correctness

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.

Example: Uncaught exception

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:

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.

Example: Exception correctness of an API

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] Note

An assert(...) might call abort(): the use of the macros above may not be suitable for testing for assert's in a portable manner.

Bibliographic references

Publications

Exceptions and Error Handling

Standard C++ Foundation


PrevUpHomeNext