• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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