UTF"> ]>
Fixtures … or let me repeat myself Fixtures In general terms a test fixture or test context is the collection of one or more of the following items, required to perform the test: preconditions particular states of tested unites necessary cleanup procedures Though these tasks are encountered in many if not all test cases, what makes a test fixture different is repetition. Where a normal test case implementation does all preparatory and cleanup work itself, a test fixture allows this to be implemented in a separate reusable unit. With introduction of extreme programming (XP), the testing style, that require test setup/cleanup repetition, is becoming more and more popular. Single XP adopted test modules may contain hundreds of single assertion test cases, many requiring very similar test setup/cleanup. This is the problem that the test fixture is designed to solve. In practice a test fixture usually is a combination of setup and teardown functions, associated with test case. The former serves the purposes of test setup; the later is dedicated to the cleanup tasks. Ideally it's preferable that a test module author is able to define variables used in fixtures on the stack and the same time is able to refer to them directly in test case. It's important to understand that C++ provides a way to implement a straightforward test fixture solution that almost satisfies our requirements without any extra support from the test framework. This may explain why test fixtures support was introduced in the &utf; somewhat late in its life cycle. Here is how simple test module with such a fixture may look like: This is a generic solution that can be used to implement any kind of shared setup or cleanup procedure. Still there are several more or less minor practical issues with this pure C++ based fixtures solution: We need to add a fixture declaration statement into each test case manually. Objects defined in fixture are references with "<fixture-instance-name>." prefix. There is no place to execute a "global" fixture, which performs "global" setup/cleanup procedures before and after testing. While there is little the &utf; can do to address these issues for manually registered test units, it's possible to resolve them for test units that are automatically registered. To do this the &utf; defines a generic fixture model - fixed interfaces that both setup and teardown fixture functions should comply to. Based on the generic fixture model, the &utf; presents solution for the following tasks: per test case fixture automation shared test suite level fixture "global" fixture support
Generic fixture model Generic model The &utf; defines the generic fixture model as follows: struct <fixture-name>{ <fixture-name>(); // setup function ~<fixture-name>(); // teardown function }; In other words a fixture is expected to be implemented as a class where the class constructor serves as a setup method and class destructor serves as teardown method. The &utf; opted to avoid explicit names in fixture interface for setup and teardown methods, since is considered most natural in C++ for tasks similar to RAII and coincides with the pure C++ solution discusses earlier. The above interface prevents you to report errors in the teardown procedure using an exception. It does make sense though: if somehow more than one fixture is assigned to a test unit, you want all teardown procedures to run, even if some may experience problems.
Per test case fixture Per test case To automate the task of assigning a fixture for the test case, for test case creation use the macro BOOST_FIXTURE_TEST_CASE in place of the macro BOOST_AUTO_TEST_CASE: The only difference from the macro BOOST_AUTO_TEST_CASE is the presence of an extra argument - fixture name. Unlike the pure C++ solution you have direct access to the public and protected members of the fixture, though you still need to refer to the fixture name in every test case. You can't access private members of fixture, but then why would you make anything private? Per test case fixture In this example only test_case1 and test_case2 have fixture F assigned. In the next section you going to see what can be done if all test cases in a test suite require the same fixture.
Test suite level fixture Test suite shared If all test cases in a test require the same fixture (you can group test cases in the test suite based on a fixture required) you can make another step toward an automation of a test fixture assignment. To assign the same shared fixture for all test cases in a test suite use the macro BOOST_FIXTURE_TEST_SUITE in place of the macro BOOST_AUTO_TEST_SUITE for automated test suite creation and registration. Once again the only difference from the macro BOOST_AUTO_TEST_SUITE usage is the presence of an extra argument - the fixture name. And now, you not only have direct access to the public and protected members of the fixture, but also do not need to refer to the fixture name in test case definition. All test cases assigned the same fixture automatically. If necessary you can reset the fixture for a particular test case with the use of the macro BOOST_FIXTURE_TEST_CASE. The fixture assignment is "deep". In other words unless reset by another BOOST_FIXTURE_TEST_SUITE or BOOST_FIXTURE_TEST_CASE definition the same fixture is assigned to all test cases, including ones that belong to the sub test suites. Test suite level fixture
Global fixture Any global initialization that needs to be performed every time testing begins or a global cleanup that is to be performed once testing is finished is called a global fixture. The &utf; global fixture design is based on a generic test fixture model and is supported by the utility class boost::unit_test::global_fixture. The global fixture design allows any number of global fixtures to be defined in any test file that constitutes a test module. Though some initialization can be implemented in the test module initialization function, there are several reasons to prefer the global fixture approach: There is no place for cleanup/teardown operations in the initialization function. Unlike the initialization function, the global fixture setup method invocation is guarded by the execution monitor. That means that all uncaught errors that occur during initialization are properly reported. Any number of different global fixtures can be defined, which allows you to split initialization code by category. The fixture allows you to place matching setup/teardown code in close vicinity in your test module code. If the whole test tree is constructed automatically the initialization function is empty and auto-generated by the &utf;. To introduce the initialization function can be more work than the use of a global fixture facility, while global fixture is more to the point. Since all fixtures follow the same generic model you can easily switch from local per test case fixtures to the global one. If you are using the interactive test runner (non-supplied yet) global test fixtures are applied to every run, while an initialization function is executed only once during a test module startup (just make sure that it's what you really want). To define a global test module fixture you need to implement a class that matched generic fixture model and passed it as an argument to the macro BOOST_GLOBAL_FIXTURE. The statement, that performs global fixture definition, has to reside at a test file scope. Global fixture