1[/ 2 / Copyright (c) 2015 Boost.Test contributors 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See accompanying 5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 /] 7 8[section:contexts Contexts] 9 10Contexts are a facility provided by the __UTF__ in order to be able to trace the location of assertions better. To grasp 11the idea, consider the following example: 12 13 14`` 15void test_operations(Processor& processor, int limit) 16{ 17 for (int i = 0; i < limit; ++i) { 18 BOOST_TEST(processor.op1(i)); 19 for (int j = 0; j < i; ++j) { 20 BOOST_TEST(processor.op2(i, j)); 21 } 22 } 23} 24`` 25 26In case of failure, in order to see in the logs at which point of the loops the failure occurred, we need some extra 27information in the assertion, which can be achieved for instance [link boost_test.testing_tools.reports.custom_messages the following way]: 28 29 30`` 31BOOST_TEST(processor.op1(i)); 32`` 33 34replaced by 35 36`` 37BOOST_TEST(processor.op1(i), "With parameter i = " << i); 38`` 39 40We see in this trivial example that a context, which is the variable `i` in this case, should be acknowledged by the 41assertion `BOOST_CHECK` in a particular way. In the approach above, this is done by adding a message to the assertion 42itself. 43 44What if the context is more complex than that? In case the complexity of the context increases, the fact that the 45assertion and the context is tightly coupled as in the approach above is difficult to maintain: 46 47`` 48void test_operations(Processor& processor, int limit, int level) 49{ 50 for (int i = 0; i < limit; ++i) { 51 BOOST_TEST(processor.op1(i), 52 "With optimization level " << level << ", With parameter i = " << i); 53 for (int j = 0; j < i; ++j) { 54 BOOST_TEST(processor.op2(i, j), 55 "With optimization level " << level << 56 ", With parameter i = " << i << ", With parameter j = " << j); 57 } 58 } 59} 60 61BOOST_AUTO_TEST_CASE(test1) 62{ 63 Processor processor; 64 65 for (int level = 0; level < 3; ++level) { 66 processor.optimization_level(level); 67 test_operations(processor, 2, level); 68 } 69} 70`` 71 72Note the length of the messages, the repetition, and the fact, that we pass argument `level` to function 73`test_operations` only for the sake of generating an error message in case of a failure. 74 75Therefore, *loose* coupling between the context of an assertion and the assertion point is a property that is desirable. 76 77[#ref_BOOST_TEST_INFO][h3 Assertion-bound context] 78 79`BOOST_TEST_INFO` can be used to define an error message to be bound to the first following assertion. If (and only 80if) the assertion fails, the bound message will be displayed along: 81 82[bt_example example80_contexts..Assertion-bound context..run-fail] 83 84The information composed inside `BOOST_TEST_INFO` is bound only to the first assertion 85following the declaration. This information is only displayed if the assertion fails; otherwise the message is 86discarded. The `BOOST_TEST_INFO` declaration does not have to immediately precede the assertion, it is allowed to 87intertwine them with other instructions, they can even be declared in different scopes. It is also possible to 88bind more than one information to a given assertion. 89 90With `BOOST_TEST_INFO`, we can improve our initial example as follows: 91 92 93`` 94void test_operations(Processor& processor, int limit, int level) 95{ 96 for (int i = 0; i < limit; ++i) { 97 BOOST_TEST_INFO("With optimization level " << level); 98 BOOST_TEST_INFO("With parameter i = " << i); 99 BOOST_TEST(processor.op1(i)); 100 for (int j = 0; j < i; ++j) { 101 BOOST_TEST_INFO("With optimization level " << level); 102 BOOST_TEST_INFO("With parameter i = " << i); 103 BOOST_TEST_INFO("With parameter j = " << j); 104 BOOST_TEST(processor.op2(i, j)); 105 } 106 } 107} 108 109BOOST_AUTO_TEST_CASE(test1) 110{ 111 Processor processor; 112 113 for (int level = 0; level < 3; ++level) { 114 processor.optimization_level(level); 115 test_operations(processor, 2, level); 116 } 117} 118`` 119 120[#ref_BOOST_TEST_CONTEXT][h3 Scope-bound context] 121 122In the previous example, the information stored inside the calls to `BOOST_TEST_INFO` were all consumed by the next assertion. There are cases 123where we would like this information be persistent for the current scope. __UTF__ provides two tools to achieve this: 124 125* `BOOST_TEST_CONTEXT` defines a diagnostic message and a scope. The message is bound to every assertion in that scope, 126 and is displayed along with every failed assertion. 127* `BOOST_TEST_INFO_SCOPE` acts the same as `BOOST_TEST_INFO`, but the stored context information is bound to all the assertions 128 that follow the call to `BOOST_TEST_INFO_SCOPE` within the current scope. 129 130[tip Since Boost [link ref_CHANGE_LOG_3_10 Boost 1.70], `BOOST_TEST_CONTEXT` can accept multiple arguments.] 131[tip `BOOST_TEST_INFO_SCOPE` has been introduced in [link ref_CHANGE_LOG_3_10 Boost 1.70].] 132 133[bt_example example81_contexts..Scope-bound context..run-fail] 134 135In the previous example, there is an opening brace right after `BOOST_TEST_CONTEXT`: this pair of braces defines the scope in which 136the diagnostic message is in effect. If there is no braces, the scope applies only to the following statement. 137`BOOST_TEST_CONTEXT` declarations can nest. 138 139With `BOOST_TEST_CONTEXT`, we can further improve our initial example, by putting variable `level` into a scope-level context 140and not pass it as function parameter: 141 142`` 143void test_operations(Processor& processor, int limit) 144{ 145 for (int i = 0; i < limit; ++i) { 146 BOOST_TEST_INFO("With parameter i = " << i); 147 BOOST_TEST(processor.op1(i)); 148 for (int j = 0; j < i; ++j) { 149 BOOST_TEST_INFO("With parameter i = " << i); 150 BOOST_TEST_INFO("With parameter j = " << j); 151 BOOST_TEST(processor.op2(i, j)); 152 } 153 } 154} 155 156BOOST_AUTO_TEST_CASE(test1) 157{ 158 Processor processor; 159 160 for (int level = 0; level < 3; ++level) { 161 BOOST_TEST_CONTEXT("With optimization level " << level) { 162 processor.optimization_level(level); 163 test_operations(processor, 2); 164 } 165 } 166} 167`` 168If we observe that variable `i` also applies in a certain scope, we can improve our example further still. 169 170[bt_example example82_contexts..Using contexts..run-fail] 171 172Finally, it is possible to pass several arguments to `BOOST_TEST_CONTEXT`, which is more convenient than having 173several scopes: 174 175[bt_example example83_contexts..Multiple arguments to `BOOST_TEST_CONTEXT`..run-fail] 176 177`BOOST_TEST_INFO_SCOPE` is convenient when you augment the current scope information as new information arrives. 178The following example calls several time a quadratic polynomial estimation function with random polynomial. As the 179random values are drawn in a loop, they are placed in the current scope with `BOOST_TEST_INFO_SCOPE`, which allows us 180to easily debug the function. 181 182[bt_example example84_contexts..Sticky context with `BOOST_TEST_INFO_SCOPE`..run-fail] 183 184[endsect] [/ contexts ] 185