1[/ 2 / Copyright (c) 2003 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:fixtures Fixtures] 9In general terms a test fixture or test context is the collection of one or more of the following items, required 10to perform the test: 11 12* preconditions 13* particular states of tested units 14* necessary cleanup procedures 15 16Though these tasks are encountered in many if not all test cases, what makes a test fixture different is 17repetition. Where a normal test case implementation does all preparatory and cleanup work itself, a test fixture 18allows it to be implemented in a separate reusable unit. 19 20With introduction of e[*X]treme [*P]rogramming (XP), the testing style, that require test setup/cleanup repetition, 21has become even more popular. Single XP adopted test modules may contain hundreds of single assertion test cases, 22many requiring very similar test setup/cleanup. This is the problem that the test fixture is designed to solve. 23 24In practice a test fixture usually is a combination of `setup` and `teardown` functions, associated with test case. 25The former serves the purposes of test setup. The later is dedicated to the cleanup tasks. Ideally we'd like for a 26test module author to be able to define variables used in fixtures on the stack and, at the same time, to refer to 27them directly in a test case. 28 29It's important to understand that C++ provides a way to implement a straightforward test fixture solution 30that almost satisfies our requirements without any extra support from the test framework. Here is how simple test 31module with such a fixture may look like: 32 33`` 34struct MyFixture { 35 MyFixture() { i = new int; *i = 0 } 36 ~MyFixture() { delete i; } 37 38 int* i; 39}; 40 41__BOOST_AUTO_TEST_CASE__( test_case1 ) 42{ 43 MyFixture f; 44 // do something involving f.i 45} 46 47__BOOST_AUTO_TEST_CASE__( test_case2 ) 48{ 49 MyFixture f; 50 // do something involving f.i 51} 52`` 53 54This is a generic solution that can be used to implement any kind of shared setup or cleanup procedure. Still 55there are several more or less minor practical issues with this pure C++ based fixtures solution: 56 57* We need to add a fixture declaration statement into each test case manually. 58* Objects defined in fixture are references with `<fixture-instance-name>` prefix. 59* There is no place to execute a ['global] fixture, which performs ['global] setup/cleanup 60 procedures before and after testing. 61 62The __UTF__ lets you define a fixture according to [link boost_test.tests_organization.fixtures.models several generic interfaces], 63and thus helps you with following tasks: 64 65* define shared setup/teardown procedures for a single or group of test cases 66* define setup/teardown procedures which are performed once per test suite 67* define [link boost_test.tests_organization.fixtures.global global setup/teardown] procedures which are performed once per test module 68 69[/ ###################################################################################### ] 70[section:models Fixture models] 71 72Several fixture interfaces are supported by the __UTF__. The choice of the interface depends 73mainly on the usage of the fixture. 74 75[h3 Fixture class model] 76The __UTF__ defines the generic fixture class model as follows: 77 78`` 79struct <fixture-name>{ 80 <fixture-name>(); // setup function 81 ~<fixture-name>(); // teardown function 82}; 83`` 84 85In other words a fixture is expected to be implemented as a class where the class constructor serves as a `setup` 86method and class destructor serves as `teardown` method. 87 88The class model above has some limitations though: 89 90* it is not possible to have exceptions in the teardown function, especially any test assertions that aborts the 91 current test case is not possible (as those use exceptions) 92* it is sometimes more natural to use the constructor/destructor to perform the necessary resource allocation/release 93 of the fixture, and that will be consumed in the test cases, and check for the proper state of the fixture in separate functions. 94 Those checks are the pre-conditions for the test case to run, and the post-conditions that should be met after the test case 95 has been running. 96 97This is why the __UTF__ also supports (Boost 1.65 on) optional `setup` and/or `teardown` functions as follow: 98 99`` 100struct <fixture-name>{ 101 <fixture-name>(); // ctor 102 ~<fixture-name>(); // dtor 103 void setup(); // setup, optional 104 void teardown(); // teardown, optional 105}; 106`` 107 108[note As mentioned, the declaration/implementation of the `setup` and `teardown` are optional: 109 the __UTF__ will check the existence of those and will call them adequately. However in C++98, 110 it is not possible to detect those declaration in case those are inherited (it works fine for 111 compiler supporting `auto` and `decltype`). 112] 113 114This model is expected from fixtures used with __BOOST_FIXTURE_TEST_CASE__ and __BOOST_FIXTURE_TEST_SUITE__. 115 116 117[h3 Flexible models] 118In addition to __BOOST_FIXTURE_TEST_CASE__ and __BOOST_FIXTURE_TEST_SUITE__ the __UTF__ allows to associate fixture with 119test unit using the decorator __decorator_fixture__. This decorator supports additional models for declaring 120the `setup` and `teardown`: 121 122* a fixture defined according to the fixture class model above 123* a fixture defined according to the extended fixture class model, which allows for the fixture constructor to 124 takes one argument. For example: 125 126 struct Fx 127 { 128 std::string s; 129 Fx(std::string s_ = "") : s(s_) 130 { BOOST_TEST_MESSAGE("ctor " << s); } 131 void setup() 132 { BOOST_TEST_MESSAGE("optional setup " << s); } 133 void teardown() 134 { BOOST_TEST_MESSAGE("optional teardown " << s); } 135 ~Fx() 136 { BOOST_TEST_MESSAGE("dtor " << s); } 137 }; 138 139* a fixture defined as a pair of free functions for the `setup` and `teardown` (latter optional) 140 141 void setup() { BOOST_TEST_MESSAGE("set up"); } 142 void teardown() { BOOST_TEST_MESSAGE("tear down"); } 143 144For complete example of test module which uses these models please check decorator __decorator_fixture__. 145 146[endsect] [/section generic fixture] 147 148 149 150[/ ###################################################################################### ] 151[section:case Test case fixture] 152A /test case fixture/ is a fixture consumed by a test case: the fixture `setup` is called before the test case executes, 153and the fixture `teardown` is called after the test case finished its execution, independently from its execution state. 154 155The __UTF__ provides several ways of defining fixtures for test-cases, each of which having their properties: 156 157* the declaration of a fixture for a single test case, letting the test case access the members of the fixture, 158* the declaration of one or more fixture(s) for a single test case, without accessing the members and with a flexible interface, 159* the declaration of a fixture for a group of test-cases defined by a subtree, with access to the members of the fixture. 160 161 162[h3 Single test case fixture] 163The following two methods are available for declaring a fixture attached to one particular test case: 164 165* the use of the macro __BOOST_FIXTURE_TEST_CASE__ in place of __BOOST_AUTO_TEST_CASE__, which let access to the members of the fixture 166* the use of the decorator __decorator_fixture__, which does not let access to the members but enables 167 the definition of several fixtures for one test case. 168 169[/ ------------------------------------------------------------------------ ] 170[#test_case_fixture_macro][h4 Fixture with `BOOST_FIXTURE_TEST_CASE`] 171 172`BOOST_FIXTURE_TEST_CASE` serves as a test case declaration with a fixture, and is meant be used in place of 173the test case declaration with __BOOST_AUTO_TEST_CASE__: 174 175`` 176 BOOST_FIXTURE_TEST_CASE(test_case_name, fixture_name); 177`` 178 179The only difference from the macro __BOOST_AUTO_TEST_CASE__ is the presence of an extra argument `fixture_name`. 180The public and protected members of the fixture are directly accessible from the test case body. Only 181one fixture can be attached to a test-case [footnote it is still possible to define a class inheriting from several 182fixtures, that will act as a proxy fixture.]. 183 184[note You can't access private members of fixture, but then why would you make anything private?] 185 186[bt_example example18..Per test case fixture..run-fail] 187 188In this example only `test_case1` and `test_case2` have fixture `F` assigned. 189You still need to refer to the fixture name in every test case. [link test_case_fixture_subtree This] section 190explains how a same fixture can be declared for a subtree under a test suite. 191 192[/ ------------------------------------------------------------------------ ] 193[#test_case_fixture_decorator][h4 Fixture with `fixture` decorator] 194By using the decorator __decorator_fixture__, it is possible to: 195 196* attach several fixtures to a unique test case 197* use a flexible fixture interface (see [link boost_test.tests_organization.fixtures.models here]) 198 199[note Using the decorator approach, it is not possible to access the members of the fixture (in case the fixture is implemented 200 as a class)] 201 202 203 204[/ ###################################################################################### ] 205[#test_case_fixture_subtree][h3 Fixture for a complete subtree] 206 207If all test cases in a test sub tree require the same fixture (you can group test cases in a test suite based on a 208fixture required) you can make another step toward an automation of a test fixture assignment. To assign the 209same shared fixture for all test cases in a test suite, use the macro __BOOST_FIXTURE_TEST_SUITE__ in place of the 210macro __BOOST_AUTO_TEST_SUITE__ for automated test suite creation and registration. 211 212`` 213 BOOST_FIXTURE_TEST_SUITE(suite_name, fixture_name); 214`` 215 216Once again the only difference from the macro __BOOST_AUTO_TEST_SUITE__ usage is the presence of 217an extra argument - the fixture name. And now, you not only have direct access to the public and protected members 218of the fixture, but also do not need to refer to the fixture name in test case definition. All test cases assigned 219the same fixture automatically. 220 221[tip If necessary you can reset the fixture for a particular test case using the macro 222 __BOOST_FIXTURE_TEST_CASE__. Similarly you can reset the fixture for a particular sub 223 test suite using __BOOST_FIXTURE_TEST_SUITE__. 224] 225 226[note The fixture assignment is ['deep]. In other words unless reset by another 227 __BOOST_FIXTURE_TEST_SUITE__ or __BOOST_FIXTURE_TEST_CASE__ definition the 228 same fixture is assigned to all test cases of a test suite, including ones that belong to the sub test suites. 229] 230 231[bt_example fixture_02..Test suite level fixture..run] 232 233[caution The fixture constructor/setup and teardown/destructor is called for each test cases (the state of the 234 fixture is not shared among the test cases).] 235 236[endsect] [/ per test case] 237 238[/ ###################################################################################### ] 239[section:per_test_suite_fixture Test suite entry/exit fixture] 240 241It is possible to define a test suite entry/exit fixture, so that the `setup` function is called only once upon entering 242the test suite, prior to running any of its test cases. 243Similarly the `teardown` function is also called only once 244upon the test suite exit, after all the enclosed test cases have been run. This is facilitated by the 245/decorator/ __decorator_fixture__. 246 247[bt_example fixture_03..Test suite entry/exit fixture..run] 248 249In case of this fixture type, however, it is not possible to access any members of the fixture object. 250 251[caution This is not equivalent to using the method described [link test_case_fixture_subtree here].] 252 253[endsect] [/ per_test_suite_fixture] 254 255[/ ###################################################################################### ] 256[section:global Global fixture] 257 258Any global initialization that needs to be performed before any test begins, or a cleanup that is to be 259performed after all tests are finished is called a /global fixture/. A global fixture is equivalent to a 260[link boost_test.tests_organization.fixtures.per_test_suite_fixture test-suite 261entry/exit] fixture (executed once), where in this case the test-suite is the 262[link boost_test.tests_organization.test_tree.master_test_suite master test suite]. 263 264The __UTF__ global fixture design is based on the 265[link boost_test.tests_organization.fixtures.models generic test class fixture model]. The global 266fixture design allows any number of global fixtures to be defined in any test file that constitutes a test module. 267Though some initialization can be implemented in the test module initialization function, there are several 268reasons to prefer the global fixture approach: 269 270* There is no place for `cleanup`/`teardown` operations in the initialization function. 271* Unlike the initialization function, the global fixture construction, `setup` and `teardown` methods invocation are guarded by the 272 execution monitor. That means that all uncaught errors that occur during initialization are properly reported. 273* Any number of different global fixtures can be defined, which allows you to split initialization code by 274 category. 275* The fixture allows you to place matching `setup`/`teardown` code in close vicinity in your test module code. 276* If the whole test tree is constructed automatically, the initialization function is empty and auto-generated by 277 the __UTF__. Introducing the initialization function can be more work than using the global fixture facility, 278 while global fixture is more to the point. 279* Since all fixtures follow the same generic model you can easily switch from local per test case fixtures to 280 the global one. 281 282To define a global test module fixture you need: 283 284# to implement a class that matches the 285 [link boost_test.tests_organization.fixtures.models fixture model] 286# and to pass the class as an argument to the macro __BOOST_TEST_GLOBAL_FIXTURE__. 287 288`` 289 BOOST_TEST_GLOBAL_FIXTURE( fixture_name ); 290`` 291 292The statement, that performs global fixture definition, has to reside at a test file scope. 293 294[bt_example fixture_04..Global fixture..run-fail] 295 296[endsect] [/section Global fixtures] 297 298[endsect] [/ section fixtures] 299 300[/EOF] 301