I am using Boost Test to unit test some C++ code.
I have a vector of values that I need to compare with expected results, but I don't want to manually check the values in a loop:
BOOST_REQUIRE_EQUAL(values.size(), expected.size());
for( int i = 0; i < size; ++i )
{
BOOST_CHECK_EQUAL(values[i], expected[i]);
}
The main problem is that the loop check doesn't print the index, so it requires some searching to find the mismatch.
I could use std::equal
or std::mismatch
on the two vectors, but that will require a lot of boilerplate as well.
Is there a cleaner way to do this?
Use
BOOST_CHECK_EQUAL_COLLECTIONS
. It's a macro intest_tools.hpp
that takes two pairs of iterators:It will report the indexes and the values that mismatch. If the sizes don't match, it will report that as well (and won't just run off the end of the vector).
Note that if you want to use
BOOST_CHECK_EQUAL
orBOOST_CHECK_EQUAL_COLLECTIONS
with non-POD types, you will need to implementfor the comparison and logging, respectively.
The order of the iterators passed to
BOOST_CHECK_EQUAL_COLLECTIONS
determines which is the RHS and LHS of the!=
comparison - the first iterator range will be the LHS in the comparisons.You can use
BOOST_REQUIRE_EQUAL_COLLECTIONS
withstd::vector<T>
, but you have to teach Boost.Test how to print astd::vector
when you have a vector of vectors or a map whose values are vectors. When you have a map, Boost.Test needs to be taught how to printstd::pair
. Since you can't change the definition ofstd::vector
orstd::pair
, you have to do this in such a way that the stream insertion operator you define will be used by Boost.Test without being part of the class definition ofstd::vector
. Also, this technique is useful if you don't want to add stream insertion operators to your system under test just to make Boost.Test happy.Here is the recipe for any
std::vector
:This formats the vectors as
[e1,e2,e3,...,eN]
for a vector withN
elements and will work for any number of nested vectors, e.g. where the elements of the vector are also vectors.Here is the similar recipe for
std::pair
:BOOST_REQUIRE_EQUAL_COLLECTIONS
will tell you the index of the mismatched items, as well as the contents of the two collections, assuming the two collections are of the same size. If they are of different sizes, then that is deemed a mismatch and the differing sizes are printed.A bit off-topic, however, when sometimes one needs to compare collections of floating-point numbers using comparison with tolerance then this snippet may be of use:
This does not print the array indexes of mismatching elements, but it does print the mismatching values with high precision, so that they are often easy to find.
Example usage:
Since Boost 1.59 it is much easier to compare
std::vector
instances. See this documentation for version 1.63 (which is nearly equal in this respect to 1.59).For example if you have declared
std::vector<int> a, b;
you can writeto get a very basic comparison. The downside of this is that in case of failure Boost only tells you that
a
andb
are not the same. But you get more info by comparing element-wise which is possible in an elegant wayOr if you want a lexicographic comparison you may do
How about BOOST_CHECK_EQUAL_COLLECTIONS?