Home | Libraries | People | FAQ | More |
Suppose we wish to test that the following function, declared in hello.hpp
and supplied by a static library hello
, inserted the text
Hello, world!\n
to the given stream
:
#if !defined(HELLO_HPP) #define HELLO_HPP #include <ostream> extern void hello_world(std::ostream& stream); #endif
We can accomplish this with the following test, saving it in test_hello.cpp
:
#define BOOST_TEST_MAIN #include <boost/test/included/unit_test.hpp> #include "hello.hpp" #include <sstream> BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); }
We compile test_hello.cpp
and link it against the static
library hello
using the build environment for our platform
to produce an executable. No other source files or libraries are needed.
When we run the executable, it will execute our test case.
Suppose that our implementation of hello_world
looks like
this:
#include "hello.hpp" void hello_world(std::ostream& stream) { }
When we run the unit test executable we obtain output similar to the following:[1]
Running 1 test case... src/tutorials/hello_test/1/test/test_hello.cpp(13): fatal error in "hello_world_inserts_text": critical check "Hello, world!\n" == dest.str() failed [Hello, world! != ] *** 1 failure detected in test suite "Master Test Suite" EXIT STATUS: 201
Oops, it looks like we forgot to implement hello_world
!.
Let's fix that by changing hello.cpp
to the following:
#include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!"; }
We can now rebuild our library, relink our unit test executable and re-run the test:
Running 1 test case... src/tutorials/hello_test/2/test/test_hello.cpp(13): fatal error in "hello_world_inserts_text": critical check "Hello, world!\n" == dest.str() failed [Hello, world! != Hello, world!] *** 1 failure detected in test suite "Master Test Suite" EXIT STATUS: 201
Oops, looks like we forgot to insert the newline character. Let's fix that
by changing hello.cpp
to the following:
#include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!" << std::endl; }
We rebuild our library, relink our unit test executable again and re-run the test:
Running 1 test case... *** No errors detected EXIT STATUS: 0
Now all our tests are passing and we know that hello_world
does what we expect it to do. We used std::endl
to insert
the newline character and it also flushes the output stream after inserting
the newline. If we didn't want the output stream to be flushed, we can change
hello_world
to use a character literal:
#include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!\n"; }
We rebuild and re-run the test to verify that our change didn't break anything:
Running 1 test case... *** No errors detected EXIT STATUS: 0
Now that we've seen Boost.Test in action, let's take a closer look at what we have just done:
<boost/test/included/unit_test.hpp>
.
We didn't link against any libraries or introduce any run-time dependencies.
main
, but our
test executable linked and ran. Why? The preprocessor symbol BOOST_TEST_MAIN
instructed Boost.Test to supply an implementation of main
that executes all tests registered with the framework.
BOOST_AUTO_TEST_CASE
registered our unit test case with the framework and provides the necessary
preamble for the implementation of the testing function.
BOOST_AUTO_TEST_CASE
is the name of our test case and is a C++ identifier, not a string.
hello_world
, the system under
test.
hello_world
.
BOOST_REQUIRE_EQUAL
.
[1]
The test runner output here is generated from the run-fail
rule in Boost.Build which includes the output from the executable and appends
the exit code of the process to the output.