...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
As mentioned earlier, one of the major aspects of using the Unit Test Framework datasets lies in the number of operations provided for their combination.
For that purpose, three operators are provided:
operator+
operator^
on datasets
operator*
Tip | |
---|---|
All these operators are associative, which enables their combination without parenthesis. However, the precedence rule on the operators for the language still apply. |
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
from the left
to the right order of the symbol +
:
dsa = (a_1, a_2, ... a_i) dsb = (b_1, b_2, ... b_j) dsa + dsb = (a_1, a_2, ... a_i, b_1, b_2, ... b_j)
The following properties hold:
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
:
( dsa + dsb ) + dsc == dsa + ( dsb + dsc ) == dsa + dsb + dsc
Warning | |
---|---|
In the expression |
Code |
---|
#define BOOST_TEST_MODULE dataset_example62 #include <boost/test/included/unit_test.hpp> #include <boost/test/data/test_case.hpp> #include <boost/test/data/monomorphic.hpp> namespace data = boost::unit_test::data; int samples1[] = {1, 2}; int samples2[] = {8, 9, 10}; BOOST_DATA_TEST_CASE( test1, data::make(samples1) + samples2, var) { std::cout << var << std::endl; } |
Output |
---|
> dataset_example62 Running 5 test cases... 1 2 8 9 10 *** No errors detected |
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
. The
resulting dataset samples order follows the left to right order against
the symbol ^
.
dsa = (a_1, a_2, ... a_i) dsb = (b_1, b_2, ... b_i) dsa ^ dsb = ( (a_1, b_1), (a_2, b_2) ... (a_i, b_i) )
The following properties hold:
the operation is associative, and it is possible to combine more than two datasets in one expression,
( dsa ^ dsb ) ^ dsc == dsa ^ ( dsb ^ dsc ) == dsa ^ dsb ^ dsc
A particular handling of the size is performed if dsa
and dsb
are of different
size. The rule is as follow:
Caution | |
---|---|
If the zip operation is not supported for your
compiler, the macro |
Code |
---|
#define BOOST_TEST_MODULE dataset_example61 #include <boost/test/included/unit_test.hpp> #include <boost/test/data/test_case.hpp> #include <boost/test/data/monomorphic.hpp> namespace data = boost::unit_test::data; int samples1[] = {1,2}; char const* samples2[] = {"qwerty", "asdfg"}; BOOST_DATA_TEST_CASE( test1, data::make(samples1)^samples2, integer_values, string_value) { std::cout << integer_values << ", " << string_value << std::endl; } |
Output |
---|
> dataset_example61 Running 2 test cases... 1, qwerty 2, asdfg *** No errors detected |
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
exactly once. The resulting dataset samples order follows the left
to right order against the symbol *
.
The rightmost dataset samples are iterated first.
dsa = (a_1, a_2, ... a_i) dsb = (b_1, b_2, ... b_j) 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))
The grid hence is similar to the mathematical notion of Cartesian product [3].
The following properties hold:
Caution | |
---|---|
If the grid operation is not supported for your
compiler, the macro |
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 - and twice
for the second xrange
- second dimension - to which it is zipped). Note that the state of
the random engine is not copied between two successive evaluations
of the first dimension.
Code |
---|
#define BOOST_TEST_MODULE dataset_example64 #include <boost/test/included/unit_test.hpp> #include <boost/test/data/test_case.hpp> #include <boost/test/data/monomorphic.hpp> namespace bdata = boost::unit_test::data; BOOST_DATA_TEST_CASE( test1, bdata::xrange(2) * bdata::xrange(3), xr1, xr2) { std::cout << "test 1: " << xr1 << ", " << xr2 << std::endl; BOOST_TEST((xr1 <= 2 && xr2 <= 3)); } BOOST_DATA_TEST_CASE( test2, bdata::xrange(3) * ( bdata::random( bdata::distribution=std::uniform_real_distribution<float>(1, 2)) ^ bdata::xrange(2) ), xr, random_sample, index) { std::cout << "test 2: " << xr << " / " << random_sample << ", " << index << std::endl; BOOST_TEST(random_sample < 1.7); // 30% chance of failure } |
Output |
---|
> dataset_example64 Running 12 test cases... test 1: 0, 0 test 1: 0, 1 test 1: 0, 2 test 1: 1, 0 test 1: 1, 1 test 1: 1, 2 test 2: 0 / 1.81472, 0 test.cpp(40): error: in "test2": check random_sample < 1.7 has failed [1.81472373 >= 1.7] Failure occurred in a following context: xr = 0; random_sample = 1.81472373; index = 0; test 2: 0 / 1.13548, 1 test 2: 1 / 1.90579, 0 test.cpp(40): error: in "test2": check random_sample < 1.7 has failed [1.905792 >= 1.7] Failure occurred in a following context: xr = 1; random_sample = 1.905792; index = 0; test 2: 1 / 1.83501, 1 test.cpp(40): error: in "test2": check random_sample < 1.7 has failed [1.83500862 >= 1.7] Failure occurred in a following context: xr = 1; random_sample = 1.83500862; index = 1; test 2: 2 / 1.12699, 0 test 2: 2 / 1.96887, 1 test.cpp(40): error: in "test2": check random_sample < 1.7 has failed [1.96886778 >= 1.7] Failure occurred in a following context: xr = 2; random_sample = 1.96886778; index = 1; *** 4 failures are detected in the test module "dataset_example64" |