[/ / Copyright (c) 2015 Boost.Test contributors / / Distributed under the Boost Software License, Version 1.0. (See accompanying / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /] [section:contexts Contexts] Contexts are a facility provided by the __UTF__ in order to be able to trace the location of assertions better. To grasp the idea, consider the following example: `` void test_operations(Processor& processor, int limit) { for (int i = 0; i < limit; ++i) { BOOST_TEST(processor.op1(i)); for (int j = 0; j < i; ++j) { BOOST_TEST(processor.op2(i, j)); } } } `` In case of failure, in order to see in the logs at which point of the loops the failure occurred, we need some extra information in the assertion: `` BOOST_TEST(processor.op1(i)); `` replaced by `` BOOST_TEST_MESSAGE(processor.op1(i), "With parameter i = " << i); `` We see in this trivial example that a context, which is the variable `i` in this case, should be acknowledged by the assertion `BOOST_CHECK` in a particular way. In the approach above, this is done by adding a message to the assertion itself. What if the context is more complex than that? In case the complexity of the context increases, the fact that the assertion and the context is tightly coupled as in the approach above is difficult to maintain: `` void test_operations(Processor& processor, int limit, int level) { for (int i = 0; i < limit; ++i) { BOOST_TEST_MESSAGE(processor.op1(i), "With optimization level " << level << ", With parameter i = " << i); for (int j = 0; j < i; ++j) { BOOST_TEST_MESSAGE(processor.op2(i, j), "With optimization level " << level << ", With parameter i = " << i << ", With parameter j = " << j); } } } BOOST_AUTO_TEST_CASE(test1) { Processor processor; for (int level = 0; level < 3; ++level) { processor.optimization_level(level); test_operations(processor, 2, level); } } `` Note the length of the messages, the repetition, and the fact, that we pass argument `level` to function `test_operations` only for the sake of generating an error message in case of a failure. Therefore, *loose* coupling between the context of an assertion and the assertion point is a property that is desirable. [#ref_BOOST_TEST_INFO][h3 Assertion-bound context] Macro `BOOST_TEST_INFO` can be used to define an error message to be bound to the first following assertion. If (and only if) the assertion fails, the bound message will be displayed along: [bt_example example80_contexts..Assertion-bound context..run-fail] Observe the following things. The information composed inside `BOOST_TEST_INFO` is bound only to the first assertion following the declaration. Thus bound information is only displayed if the assertion fails; otherwise the message is discarded. The `BOOST_TEST_INFO` declaration does not have to immediately precede the assertion, it is allowed to intertwine them with other instructions, they can even be declared in different scopes. Therefore it is also possible to bind more than one information to a given assertion. With `BOOST_TEST_INFO`, we can improve our initial example as follows: `` void test_operations(Processor& processor, int limit, int level) { for (int i = 0; i < limit; ++i) { BOOST_TEST_INFO("With optimization level " << level); BOOST_TEST_INFO("With parameter i = " << i); BOOST_TEST(processor.op1(i)); for (int j = 0; j < i; ++j) { BOOST_TEST_INFO("With optimization level " << level); BOOST_TEST_INFO("With parameter i = " << i); BOOST_TEST_INFO("With parameter j = " << j); BOOST_TEST(processor.op2(i, j)); } } } BOOST_AUTO_TEST_CASE(test1) { Processor processor; for (int level = 0; level < 3; ++level) { processor.optimization_level(level); test_operations(processor, 2, level); } } `` [#ref_BOOST_TEST_CONTEXT][h3 Scope-bound context] Macro `BOOST_TEST_CONTEXT` defines a diagnostic message and a scope. The message is bound to every assertion in the scope, and is displayed along with every failed assertion. [bt_example example81_contexts..Scope-bound context..run-fail] Observe the following things. After the `BOOST_TEST_CONTEXT` macro we have a pair of braces: they define the scope in which the diagnostic message is in effect. If there is no braces, the scope applies only to the following statement. `BOOST_TEST_CONTEXT` declarations can nest. With `BOOST_TEST_CONTEXT`, we can further improve our initial example, by putting variable `level` into a scope-level context and not pass it as function parameter: `` void test_operations(Processor& processor, int limit) { for (int i = 0; i < limit; ++i) { BOOST_TEST_INFO("With parameter i = " << i); BOOST_TEST(processor.op1(i)); for (int j = 0; j < i; ++j) { BOOST_TEST_INFO("With parameter i = " << i); BOOST_TEST_INFO("With parameter j = " << j); BOOST_TEST(processor.op2(i, j)); } } } BOOST_AUTO_TEST_CASE(test1) { Processor processor; for (int level = 0; level < 3; ++level) { BOOST_TEST_CONTEXT("With optimization level " << level) { processor.optimization_level(level); test_operations(processor, 2); } } } `` If we observe that variable `i` also applies in a certain scope, we can improve our example further still. [bt_example example82_contexts..Using contexts..run-fail] [endsect] [/ contexts ]