]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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:test_case_generation Data-driven test cases] | |
9 | ||
10 | ||
11 | [h4 Why data-driven test cases?] | |
12 | Some tests are required to be repeated for a series of different input parameters. One way to achieve this is | |
13 | manually register a test case for each parameter. You can also invoke a test function with | |
14 | all parameters manually from within your test case, like this: | |
15 | ||
16 | `` | |
17 | void single_test( int i ) | |
18 | { | |
19 | __BOOST_TEST__( /* test assertion */ ); | |
20 | } | |
21 | ||
22 | void combined_test() | |
23 | { | |
24 | int params[] = { 1, 2, 3, 4, 5 }; | |
25 | std::for_each( params, params+5, &single_test ); | |
26 | } | |
27 | `` | |
28 | ||
29 | The approach above has several drawbacks: | |
30 | ||
31 | * the logic for running the tests is inside a test itself: `single_test` in the above example is run from the test | |
32 | case `combined_test` while its execution would be better handled by the __UTF__ | |
33 | * in case of fatal failure for one of the values in `param` array above (say a failure in __BOOST_TEST_REQUIRE__), | |
34 | the test `combined_test` is aborted and the next test-case in the test tree is executed. | |
35 | * in case of failure, the reporting is not accurate enough: the test should certainly be reran during debugging | |
36 | sessions by a human or additional logic for reporting should be implemented in the test itself. | |
37 | ||
38 | [h4 Parameter generation, scalability and composition] | |
39 | In some circumstance, one would like to run a parametrized test over an /arbitrary large/ set of values. Enumerating the | |
40 | parameters by hand is not a solution that scales well, especially when these parameters can be described in another | |
41 | function that generates these values. However, this solution has also limitations | |
42 | ||
43 | * *Generating functions*: suppose we have a function `func(float f)`, where `f` is any number in [0, 1]. We are not | |
44 | interested that much in the exact value, but we would like to test `func`. What about, instead of writing the `f` | |
45 | for which `func` will be tested against, we choose randomly `f` in [0, 1]? And also what about instead of having | |
46 | only one value for `f`, we run the test on arbitrarily many numbers? We easily understand from this small example | |
47 | that tests requiring parameters are more powerful when, instead of writing down constant values in the test, a | |
48 | generating function is provided. | |
49 | ||
50 | * *Scalability*: suppose we have a test case on `func1`, on which we test `N` values written as constant in the test | |
51 | file. What does the test ensure? We have the guaranty that `func1` is working on these `N` values. Yet in this | |
52 | setting `N` is necessarily finite and usually small. How would we extend or scale `N` easily? One solution is to | |
53 | be able to generate new values, and to be able to define a test on the *class* of possible inputs for `func1` on | |
54 | which the function should have a defined behavior. To some extent, `N` constant written down in the test are just | |
55 | an excerpt of the possible inputs of `func1`, and working on the class of inputs gives more flexibility and power | |
56 | to the test. | |
57 | ||
58 | * *Composition*: suppose we already have test cases for two functions `func1` and `func2`, taking as argument the | |
59 | types `T1` and `T2` respectively. Now we would like to test a new functions `func3` that takes as argument a type | |
60 | `T3` containing `T1` and `T2`, and calling `func1` and `func2` through a known algorithm. An example of such a | |
61 | setting would be | |
62 | `` | |
63 | // Returns the log of x | |
64 | // Precondition: x strictly positive. | |
65 | double fast_log(double x); | |
66 | ||
67 | // Returns 1/(x-1) | |
68 | // Precondition: x != 1 | |
69 | double fast_inv(double x); | |
70 | ||
71 | struct dummy { | |
72 | unsigned int field1; | |
73 | unsigned int field2; | |
74 | }; | |
75 | ||
76 | double func3(dummy value) | |
77 | { | |
78 | return 0.5 * (exp(fast_log(value.field1))/value.field1 + value.field2/fast_inv(value.field2)); | |
79 | } | |
80 | ||
81 | `` | |
82 | ||
83 | In this example, | |
84 | ||
85 | * `func3` inherits from the preconditions of `fast_log` and `fast_inv`: it is defined in `(0, +infinity)` and in `[-C, +C] - {1}` for `field1` and `field2` respectively (`C` | |
86 | being a constant arbitrarily big). | |
87 | * as defined above, `func3` should be close to 1 everywhere on its definition domain. | |
88 | * we would like to reuse the properties of `fast_log` and `fast_inv` in the compound function `func3` and assert that `func3` is well defined over an arbitrary large definition domain. | |
89 | ||
90 | Having parametrized tests on `func3` hardly tells us about the possible numerical properties or instabilities close to the point `{field1 = 0, field2 = 1}`. | |
91 | Indeed, the parametrized test may test for some points around (0,1), but will fail to provide an *asymptotic behavior* of the function close to this point. | |
92 | ||
93 | [h4 Data driven tests in the Boost.Test framework] | |
94 | The facilities provided by the __UTF__ addressed the issues described above: | |
95 | ||
96 | * the notion of *datasets* eases the description of the class of inputs for test cases. The datasets also implement several | |
97 | operations that enable their combinations to create new, more complex datasets, | |
98 | * two macros, __BOOST_DATA_TEST_CASE__ and __BOOST_DATA_TEST_CASE_F__, respectively without and with fixture support, | |
99 | are used for the declaration and registration of a test case over a collection of values (samples), | |
100 | * each test case, associated to a unique value, is executed independently from others. These tests are guarded in the same | |
101 | way regular test cases are, which makes the execution of the tests over each sample of a dataset isolated, robust, | |
102 | repeatable and ease the debugging, | |
103 | * several datasets generating functions are provided by the __UTF__ | |
104 | ||
105 | The remainder of this section covers the notions and feature provided by the __UTF__ about the data-driven test cases, in | |
106 | particular: | |
107 | ||
108 | # the notion of [link boost_test.tests_organization.test_cases.test_case_generation.datasets *dataset* and *sample*] is introduced | |
109 | # [link boost_test.tests_organization.test_cases.test_case_generation.datasets_auto_registration the declaration and registration] | |
110 | of the data-driven test cases are explained, | |
111 | # the [link boost_test.tests_organization.test_cases.test_case_generation.operations /operations/] on datasets are detailed | |
112 | # and finally the built-in [link boost_test.tests_organization.test_cases.test_case_generation.generators dataset generators] | |
113 | are introduced. | |
114 | ||
115 | ||
116 | [/ ################################################################################################################################## ] | |
117 | [section Datasets] | |
118 | ||
119 | To define properly datasets, the notion of *sample* should be introduced first. A *sample* is defined as /polymorphic tuple/. | |
120 | The size of the tuple will be by definition the *arity* of the sample itself. | |
121 | ||
122 | A *dataset* is a /collection of samples/, that | |
123 | ||
124 | * is forward iterable, | |
125 | * can be queried for its `size`, which in turn can be infinite, | |
126 | * has an arity, which is the arity of the samples it contains. | |
127 | ||
128 | Hence the dataset implements the notion of /sequence/. | |
129 | ||
130 | The descriptive power of the datasets in __UTF__ comes from | |
131 | ||
132 | * the [link boost_test.tests_organization.test_cases.test_case_generation.datasets.dataset_interface interface] for creating a custom datasets, which is quite simple, | |
133 | * the [link boost_test.tests_organization.test_cases.test_case_generation.operations operations] they provide for combining different datasets | |
134 | * their interface with other type of collections (`stl` containers, `C` arrays) | |
135 | * the available built-in [link boost_test.tests_organization.test_cases.test_case_generation.generators /dataset generators/] | |
136 | ||
137 | [tip Only "monomorphic" datasets are supported, which means that all samples in a dataset have the same type and same arity | |
138 | [footnote polymorphic datasets will be considered in the future. Their need is mainly driven by the replacement of the | |
139 | [link boost_test.tests_organization.test_cases.test_organization_templates typed parametrized test cases] by the dataset-like API.] | |
140 | . | |
141 | ] | |
142 | ||
143 | As we will see in the next sections, datasets representing collections of different types may be combined together (e.g.. /zip/ or /grid/). | |
144 | These operations result in new datasets, in which the samples are of an augmented type. | |
145 | ||
146 | [h4 Dataset interface] | |
147 | The interface of the /dataset/ should implement the two following functions/fields: | |
148 | ||
149 | * `iterator begin()` where /iterator/ is a forward iterator, | |
150 | * `boost::unit_test::data::size_t size() const` indicates the size of the dataset. The returned type is a dedicated | |
151 | class [classref boost::unit_test::data::size_t size_t] that can indicate an /infinite/ dataset size. | |
152 | * an enum called `arity` indicating the arity of the samples returned by the dataset | |
153 | ||
154 | Once a dataset class `D` is declared, it should be registered to the framework by specializing the class ``boost::unit_test::data::monomorphic::is_dataset`` | |
155 | with the condition that ``boost::unit_test::data::monomorphic::is_dataset<D>::value`` evaluates to `true`. | |
156 | ||
157 | The following example implements a custom dataset generating a Fibonacci sequence. | |
158 | ||
159 | [bt_example dataset_example68..Example of custom dataset..run-fail] | |
160 | ||
161 | [endsect] [/ datasets] | |
162 | ||
163 | ||
164 | [/ ################################################################################################################################## ] | |
165 | [/ Main code import for this section ] | |
166 | [import ../snippet/dataset_1/test_file.cpp] | |
167 | ||
168 | [/ ################################################################################################################################## ] | |
169 | [section:datasets_auto_registration Declaring and registering test cases with datasets] | |
170 | In order to declare and register a data-driven test-case, the macros __BOOST_DATA_TEST_CASE__ or __BOOST_DATA_TEST_CASE_F__ | |
171 | should be used. Those two forms are equivalent, with the difference that `BOOST_DATA_TEST_CASE_F` supports fixtures. | |
172 | ||
173 | Those macros are variadic and can be used in the following forms: | |
174 | ||
175 | `` | |
176 | __BOOST_DATA_TEST_CASE__(test_case_name, dataset) { /* dataset1 of arity 1 */ } | |
177 | BOOST_DATA_TEST_CASE(test_case_name, dataset, var1) { /* datasets of arity 1 */ } | |
178 | BOOST_DATA_TEST_CASE(test_case_name, dataset, var1, ..., varN) { /* datasets of arity N */ } | |
179 | ||
180 | __BOOST_DATA_TEST_CASE_F__(fixture, test_case_name, dataset) { /* dataset1 of arity 1 with fixture */ } | |
181 | BOOST_DATA_TEST_CASE_F(fixture, test_case_name, dataset, var1) { /* dataset1 of arity 1 with fixture */ } | |
182 | BOOST_DATA_TEST_CASE_F(fixture, test_case_name, dataset, var1, ..., varN) { /* dataset1 of arity N with fixture */ } | |
183 | `` | |
184 | ||
185 | The first form of the macro is for datasets of arity 1. The value of the sample being executed by the test body is | |
186 | available through the automatic variable `sample` (`xrange` is as its name suggests a range of values): | |
187 | ||
188 | [snippet_dataset1_1] | |
189 | ||
190 | The second form is also for datasets of arity 1, but instead of the variable `sample`, the current sample is brought into `var1`: | |
191 | [snippet_dataset1_2] | |
192 | ||
193 | The third form is an extension of the previous form for datasets of arity `N`. The sample being a polymorphic tuple, each | |
194 | of the variables `var1`, ..., `varN` corresponds to the index 1, ... `N` of the the sample: | |
195 | ||
196 | [snippet_dataset1_3] | |
197 | ||
198 | The next three forms of declaration, with `BOOST_DATA_TEST_CASE_F`, are equivalent to the previous ones, with the difference being in the support of | |
199 | a fixture that is execute before the test body for each sample. The fixture should follow the expected interface as detailed | |
200 | [link boost_test.tests_organization.fixtures.models here]. | |
201 | ||
202 | The arity of the dataset and the number of variables should be exactly the same, the first form being a short-cut for the | |
203 | case of arity 1. | |
204 | ||
205 | [tip A compilation-time check is performed on the coherence of the arity of the dataset and the number of variables `var1`... `varN`. | |
206 | For compilers *without C++11* support, the maximal supported arity is controlled by the macro | |
207 | __BOOST_TEST_DATASET_MAX_ARITY__, that can be overridden /prior/ to including the __UTF__ headers.] | |
208 | ||
209 | [caution The macros __BOOST_DATA_TEST_CASE__ and __BOOST_DATA_TEST_CASE_F__ are available only for compilers with support for *variadic macros*.] | |
210 | ||
211 | [h4 Samples and test tree] | |
212 | It should be emphasized that those macros do not declare a single test case (as __BOOST_AUTO_TEST_CASE__ would do) but declare and | |
213 | register as many test cases as there are samples in the dataset given in argument. Each test case runs on exactly *one* | |
214 | sample of the dataset. | |
215 | ||
216 | More precisely, what | |
217 | ``__BOOST_DATA_TEST_CASE__(test_case_name, dataset)`` | |
218 | ||
219 | does is the following: | |
220 | ||
221 | * it registers a *test suite* named "`test_case_name`", | |
222 | * it registers as many test cases as they are in "`dataset`", each of which with the name corresponding to the index of the sample in the database prefixed by `_` and | |
223 | starting at index `0` ("`_0`", "`_1`", ... "`_(N-1)`" where `N` is the size of the dataset) | |
224 | ||
225 | This make it easy to: | |
226 | ||
227 | * identify which sample is failing (say "`test_case_name/_3`") | |
228 | * allows a replay of one or several samples (or the full dataset) from the command line using the [link boost_test.runtime_config.test_unit_filtering test filtering facility] provided by the __UTF__ | |
229 | ||
230 | Exactly as regular test cases, each test case (associated to a specific sample) is executed within the test body in a /guarded manner/: | |
231 | ||
232 | * the test execution are independent: if an error occurs for one sample, the remaining samples execution is not affected | |
233 | * in case of error, the [link boost_test.test_output.test_tools_support_for_logging.contexts context] within which the error occurred is reported in the [link boost_test.test_output log] along with | |
234 | the failing sample index. This context contains the sample for which the test failed, which would ease the debugging. | |
235 | ||
236 | [endsect] | |
237 | ||
238 | ||
239 | ||
240 | ||
241 | [/ ################################################################################################################################## ] | |
242 | [section:operations Operations on dataset] | |
243 | As mentioned earlier, one of the major aspects of using the __UTF__ datasets lies in the number of operations provided | |
244 | for their combination. | |
245 | ||
246 | For that purpose, three operators are provided: | |
247 | ||
248 | * joins with `operator+` | |
249 | * zips with `operator^` on datasets | |
250 | * and grids or Cartesian products with `operator*` | |
251 | ||
252 | [tip All these operators are associative, which enables their combination without parenthesis. However, the precedence rule on the | |
253 | operators for the language still apply. ] | |
254 | ||
255 | [section Joins] | |
256 | A ['join], denoted `+`, is an operation on two datasets `dsa` and `dsb` of same arity and compatible types, resulting in the *concatenation* of these two datasets `dsa` and `dsb` | |
257 | from the left to the right order of the symbol `+`: | |
258 | ||
259 | `` | |
260 | dsa = (a_1, a_2, ... a_i) | |
261 | dsb = (b_1, b_2, ... b_j) | |
262 | dsa + dsb = (a_1, a_2, ... a_i, b_1, b_2, ... b_j) | |
263 | `` | |
264 | ||
265 | The following properties hold: | |
266 | ||
267 | * the resulting dataset is of same arity as the operand datasets, | |
268 | * the size of the returned dataset is the sum of the size of the joined datasets, | |
269 | * the operation is associative, and it is possible to combine more than two datasets in one expression. The following joins are equivalent for any datasets `dsa`, `dsb` and `dsc`: | |
270 | `` | |
271 | ( dsa + dsb ) + dsc | |
272 | == dsa + ( dsb + dsc ) | |
273 | == dsa + dsb + dsc | |
274 | `` | |
275 | ||
276 | [warning In the expression `dsa + dsb`, `dsa` and/or `dsb` can be of infinite size. The resulting dataset will have an infinite size as well. If `dsa` is infinite, the content of | |
277 | `dsb` will never be reached. ] | |
278 | ||
279 | [bt_example dataset_example62..Example of join on datasets..run] | |
280 | ||
281 | [endsect] | |
282 | ||
283 | ||
284 | [section Zips] | |
285 | A ['zip], denoted `^` , is an operation on two datasets `dsa` and `dsb` of same arity and same size, resulting in a dataset where the `k`-th sample of `dsa` is paired with the corresponding `k`-th sample of `dsb`. | |
286 | The resulting dataset samples order follows the left to right order against the symbol `^`. | |
287 | ||
288 | `` | |
289 | dsa = (a_1, a_2, ... a_i) | |
290 | dsb = (b_1, b_2, ... b_i) | |
291 | dsa ^ dsb = ( (a_1, b_1), (a_2, b_2) ... (a_i, b_i) ) | |
292 | `` | |
293 | ||
294 | The following properties hold: | |
295 | ||
296 | * the arity of the resulting dataset is the sum of the arities of the operand datasets, | |
297 | * the size of the resulting dataset is equal to the size of the datasets (since they are supposed to be of the same size), | |
298 | exception made for the case the operand datasets size mismatch (see below), | |
299 | * the operation is associative, and it is possible to combine more than two datasets in one expression, | |
300 | `` | |
301 | ( dsa ^ dsb ) ^ dsc | |
302 | == dsa ^ ( dsb ^ dsc ) | |
303 | == dsa ^ dsb ^ dsc | |
304 | `` | |
305 | ||
306 | A particular handling is performed if `dsa` and `dsb` are of different size. The rule is as follow: | |
307 | ||
308 | * if the both zipped datasets have the same size, this is the size of the resulting dataset (this size can then be infinite). | |
309 | * otherwise if one of the dataset is of size 1 (singleton) or of infinite size, the resulting size is governed by the other dataset. | |
310 | * otherwise an exception is thrown at runtime | |
311 | ||
312 | ||
313 | [caution If the /zip/ operation is not supported for your compiler, the macro [macroref BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE `BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE`] | |
314 | will be automatically set by the __UTF__] | |
315 | ||
316 | [bt_example dataset_example61..Example of zip on datasets..run] | |
317 | ||
318 | ||
319 | [endsect] [/ zip operation on datasets] | |
320 | ||
321 | ||
322 | ||
323 | [section Grid (Cartesian products)] | |
324 | A ['grid], denoted `*` , is an operation on two any datasets `dsa` and `dsb` resulting in a dataset where each sample of `dsa` is paired with each sample of `dsb` | |
325 | exactly once. The resulting dataset samples order follows the left to right order against the symbol `*`. The rightmost dataset samples are iterated first. | |
326 | ||
327 | `` | |
328 | dsa = (a_1, a_2, ... a_i) | |
329 | dsb = (b_1, b_2, ... b_j) | |
330 | dsa * dsb = ((a_1, b_1), (a_1, b_2) ... (a_1, b_j), (a_2, b_1), ... (a_2, b_j) ... (a_i, b_1), ... (a_i, b_j)) | |
331 | `` | |
332 | ||
333 | The grid hence is similar to the mathematical notion of Cartesian product [footnote if the sequence is viewed as a set]. | |
334 | ||
335 | The following properties hold: | |
336 | ||
337 | * the arity of the resulting dataset is the sum of the arities of the operand datasets, | |
338 | * the size of the resulting dataset is the product of the sizes of the datasets, | |
339 | * the operation is associative, and it is possible to combine more than two datasets in one expression, | |
340 | * as for /zip/, there is no need the dataset to have the same type of samples. | |
341 | ||
342 | [caution If the /grid/ operation is not supported for your compiler, the macro [macroref BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE `BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE`] | |
343 | will be automatically set by the __UTF__] | |
344 | ||
345 | In the following example, the random number generator is the second dataset. Its state is evaluated 6 times (3 times for the first `xrange` - first dimension - | |
346 | and twice for the second `xrange` - second dimension - to which it is zipped). Note that the state of the random engine is | |
347 | not copied between two successive evaluations of the first dimension. | |
348 | ||
349 | [bt_example dataset_example64..Example of Cartesian product..run-fail] | |
350 | ||
351 | ||
352 | [endsect] | |
353 | ||
354 | ||
355 | ||
356 | ||
357 | [endsect] [/ operations on dataset] | |
358 | ||
359 | ||
360 | ||
361 | [/ ################################################################################################################################## ] | |
362 | [section:generators Datasets generators] | |
363 | Several ['generators] for datasets are implemented in __UTF__: | |
364 | ||
365 | * [link boost_test.tests_organization.test_cases.test_case_generation.generators.singletons Singletons] | |
366 | * [link boost_test.tests_organization.test_cases.test_case_generation.generators.stl `forward iterable`] containers and | |
367 | [link boost_test.tests_organization.test_cases.test_case_generation.generators.c_arrays `C` array] like datasets | |
368 | * [link boost_test.tests_organization.test_cases.test_case_generation.generators.ranges ranges] or sequences of values | |
369 | * datasets made of [link boost_test.tests_organization.test_cases.test_case_generation.generators.random random numbers] and following a particular distribution | |
370 | ||
371 | `stl` and `C-array` generators are merely a dataset view on existing collection, while ranges and random number sequences are | |
372 | describing new datasets. | |
373 | ||
374 | ||
375 | [/ ################################################################################################################################## ] | |
376 | [h4:singletons Singletons] | |
377 | ||
378 | A singleton is a dataset containing a unique value. The size and arity of such a dataset is 1. This value can be | |
379 | ||
380 | * either consumed once | |
381 | * or repeated as many times as needed in a zip operation | |
382 | ||
383 | As mentioned in /zip/, when zipped with a distribution of infinite size, the resulting dataset will have | |
384 | a size of 1. | |
385 | ||
386 | The singleton is constructible through the function [funcref boost::unit_test::data::make]. | |
387 | ||
388 | [bt_example dataset_example65..Singleton..run] | |
389 | ||
390 | ||
391 | ||
392 | [/ ################################################################################################################################## ] | |
393 | [h4:c_arrays Datasets from C arrays] | |
394 | This type of datasets does not contains the logic for generating the sequence of values, and is used as a wrapper on an existing | |
395 | sequence contained in a `C` array. The arity is 1 and the size is the size of the array. | |
396 | ||
397 | Such datasets are simply constructed from an overload of the [funcref boost::unit_test::data::make `make`] function. | |
398 | ||
399 | [bt_example dataset_example66..Array..run] | |
400 | ||
401 | [/ ################################################################################################################################## ] | |
402 | [h4:stl Datasets from forward iterable containers] | |
403 | As for `C` arrays, this type of datasets does not contain the logic for generating sequence of values, and are used for parsing an existing sequence. | |
404 | The arity is 1 and the size is the same as the one of the container. | |
405 | ||
406 | ||
407 | [tip C++11 implementation enables the dataset generation from any container which iterator implements the forward iterator concept. | |
408 | For C++03, the feature is enabled on most STL containers.] | |
409 | ||
410 | [bt_example dataset_example67..Dataset from `std::vector` and `std::map`..run] | |
411 | ||
412 | ||
413 | ||
414 | [/ ################################################################################################################################## ] | |
415 | [h4:ranges Ranges] | |
416 | A range is a dataset that implements a sequence of equally spaced values, defined by a /start/, and /end/ and a /step/. | |
417 | ||
418 | It is possible to construct a range using the factory [funcref boost::unit_test::data::xrange], available in the overloads below: | |
419 | ||
420 | `` | |
421 | #include <boost/test/data/test_case.hpp> | |
422 | #include <boost/test/data/monomorphic.hpp> | |
423 | ||
424 | auto range1 = data::xrange( (data::step = 0.5, data::end = 3 ) ); // Constructs with named values, starting at 0 | |
425 | auto range2 = data::xrange( begin, end ); // begin < end required | |
426 | auto range5 = data::xrange( begin, end, step ); // begin < end required | |
427 | auto range3 = data::xrange( end ); // begin=0, end cannot be <= 0, see above | |
428 | auto range4 = data::xrange( end, (data::begin=1) ); // named value after end | |
429 | `` | |
430 | ||
431 | [tip The named value parameters should be declared inside parenthesis] | |
432 | ||
433 | [h5 Parameters] | |
434 | The details of the named value parameters is given in the table below. | |
435 | [table:id_range_parameter_table Range parameters | |
436 | [ | |
437 | [Name] | |
438 | [Default] | |
439 | [Description] | |
440 | ] | |
441 | [ | |
442 | [`begin`] | |
443 | [0] | |
444 | [Beginning of the generated sequence. The `begin` value is included in set of values returned | |
445 | by the generator. | |
446 | ] | |
447 | ] | |
448 | ||
449 | [ | |
450 | [`end`] | |
451 | [+ infinity] | |
452 | [End of the generated sequence. The `end` value is not included in set of values returned | |
453 | by the generator. If omitted, the generator has infinite size. | |
454 | ] | |
455 | ] | |
456 | ||
457 | [ | |
458 | [`step`] | |
459 | [1] | |
460 | [Number indicating the step between two consecutive samples of the generated range. | |
461 | The default type is the same as the input type. This value should not be 0. It should be of the same | |
462 | sign as `end-begin`. | |
463 | ] | |
464 | ] | |
465 | ] | |
466 | ||
467 | [bt_example dataset_example59..Declaring a test with a range..run-fail] | |
468 | ||
469 | ||
470 | ||
471 | [/ ################################################################################################################################## ] | |
472 | [h4:random Random value dataset] | |
473 | ||
474 | This type of dataset generates a sequence of random numbers following a given /distribution/. The /seed/ and the /engine/ may also be | |
475 | specified. | |
476 | ||
477 | ||
478 | [caution The random value generator is available only for C++11 capable compilers. If this feature is not supported for your compiler, | |
479 | the macro [macroref BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE `BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE`] | |
480 | will be automatically set by the __UTF__] | |
481 | ||
482 | ||
483 | ||
484 | It is possible to construct a random sequence using the factory [funcref boost::unit_test::data::random], available in the overloads below: | |
485 | ||
486 | `` | |
487 | auto rdgen = random(); // uniform distribution (real) on [0, 1) | |
488 | auto rdgen = random(1, 17); // uniform distribution (integer) on [1, 17] | |
489 | // Default random generator engine, Gaussian distribution (mean=5, sigma=2) and seed set to 100. | |
490 | auto rdgen = random( (data::seed = 100UL, | |
491 | data::distribution = std::normal_distribution<>(5.,2)) ); | |
492 | `` | |
493 | ||
494 | Since the generated datasets will have infinite size, the sequence size should be narrowed by combining the dataset with another | |
495 | one through e.g. a /zip/ operation. | |
496 | ||
497 | [tip In order to be able to reproduce a failure within a randomized parameter test case, the seed that generated the failure may be | |
498 | set in order to generate the same sequence of random values.] | |
499 | ||
500 | [h5 Parameters] | |
501 | The details of the named value parameters is given in the table below. | |
502 | [table:id_range_parameter_table Range parameters | |
503 | [ | |
504 | [Parameter name] | |
505 | [Default] | |
506 | [Description] | |
507 | ] | |
508 | [ | |
509 | [`seed`] | |
510 | [(not set)] | |
511 | [Seed for the generation of the random sequence.] | |
512 | ] | |
513 | [ | |
514 | [`distribution`] | |
515 | [Uniform] | |
516 | [Distribution instance for generating the random number sequences. The `end` value is not included in set of values returned | |
517 | by the generator for real values, and is included for integers. ] | |
518 | ] | |
519 | [ | |
520 | [`engine`] | |
521 | [`std::default_random_engine`] | |
522 | [Random number generator engine.] | |
523 | ] | |
524 | ] | |
525 | ||
526 | [bt_example dataset_example63..Declaring a test with a random sequence..run-fail] | |
527 | ||
528 | ||
529 | [endsect] [/ Datasets generators] | |
530 | ||
531 | [endsect] |