fixtures.qbk 14 KB

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