Re: [googletest] Writing custom Assertions with GTest

1,951 views
Skip to first unread message

Matthew Woehlke

unread,
Sep 24, 2012, 12:59:15 PM9/24/12
to googletes...@googlegroups.com
If I understand what you want to do, it sounds like what you are looking
for is a way to define your own assertion functions, e.g.
EXPECT_VECTOR_ROUGHLY_EQUAL(y, x) which would compare vector elements
one by one. (Although for this particular case, it seems like eigen
should already have something to do that... but certainly there are
cases where that is not true.)

Usually what I do is:

#define TEST_CALL(statement) \
do { \
SCOPED_TRACE(""); \
statement; \
} while(0)

#define EXPECT_VECTOR_ROUGHLY_EQUAL(...) \
TEST_CALL(test_vectors_roughly_equal(__VA_ARGS__))

void test_vectors_roughly_equal(T const& expected, T const& actual)
{
ASSERT_EQ(expected.length(), actual.length());
for (size_t n = 0; n < expected.length; ++n)
EXPECT_EQ(expected[n], actual[n]) << " at " << n;
}

Obviously there is a lot of omission and abbreviation in the above, but
it should give you the idea. Note that an ASSERT in the assertion
function only quits the function, not the entire test. (In the example,
you definitely want an ASSERT, since continuing on to compare elements
is pointless if the sizes differ, besides that the for loop would have
to be more complex to prevent the code breaking in such case.) The
TEST_CALL macro is a convenience to give you the line in your test case
where a failure occurs, and not just the line in the assertion function.

Use of varargs in the assertion macro is optional (the whole macro is
optional, in fact, though I feel that using it cuts down on boilerplate
that might get in the way of understanding the intent of the code), but
allows you to use overloading to have different versions of the
assertion function taking a different number of arguments, which might
be useful. (It's also just plain convenient if you have a lot of
arguments, as some of my incarnations of this paradigm do.)

Matthew

On 2012-09-22 11:14, Abhijit Kundu wrote:
> Hi all,
>
> I am very new to unit-testing and GTest. I am looking for a good solution
> to assert custom objects e.g. Matrices or Vectors from the Eigen<http://eigen.tuxfamily.org/>
> library.
>
> One simple way to do this is by comparing the norm, which is a scalar. For
> example, asserting equality of two vectors( say Eigen:Vector2d) x and y can
> be done as
>
>> EXPECT_NEAR(0, (x -y).norm(), 1e-10);
>
>
> However a better solution is to probably 1st check the dimensions of the
> matrices and then use the existing floating point macros to assert
> individual elements. I would like to know the best practice for doing this
> or if someone can show me a link to a similar example.
>
> Abhijit
>

Vlad Losev

unread,
Sep 24, 2012, 1:36:31 PM9/24/12
to Google C++ Testing Framework
This code can be made more user friendly by turning it into a custom comparison predicate and using it with Google Test's predicate assertion macros as described in the Advanced Guide wiki page. There are three ways to do it; the ways that require more implementation effort also produce better error messages.

Regards,
Vlad

Matthew Woehlke

unread,
Sep 24, 2012, 1:58:54 PM9/24/12
to googletes...@googlegroups.com
...except the many-arguments function I mentioned takes 10 arguments.
And you can't use ASSERT_* in a predicate function.

For Abhijit's use case, predicates *might* be valuable, but TBH I don't
see a benefit over my approach. (Yes, you can ASSERT on the function,
but you could write an equivalent of my TEST_CALL that would do likewise.)

Assuming that the assertions in the test function print the relevant
arguments on failure, there is little or no added benefit to printing
*all* the arguments to a recursively-called function, but there is the
detriment that there is only one "result" of the predicate, whereas my
approach allows many assertions in the called function.

Matthew

On 2012-09-24 13:36, Vlad Losev wrote:
> This code can be made more user friendly by turning it into a custom
> comparison predicate and using it with Google Test's predicate assertion
> macros as described in the Advanced
> Guide<http://code.google.com/p/googletest/wiki/AdvancedGuide#Predicate_Assertions_for_Better_Error_Messages>
>>> http://eigen.tuxfamily.**org/ <http://eigen.tuxfamily.org/>>
Reply all
Reply to author
Forward
0 new messages