Comparison of floating point arrays using google test and google mock
Asked Answered
P

3

6

I am new to Google's test products and trying them out with some signal processing code. I am trying to assert that to floating point arrays are equal to within some bounds, using google mock as suggested by the answer to this question. I would like to know the recommended method for adding some error tolerance to an expression like the following . . .

EXPECT_THAT(  impulse, testing::ElementsAreArray( std::vector<float>({
    0, 0, 0, 1, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
}) )  );

I want the test to pass if the element-wise values in the arrays are within 10-8 of one another.

Pelagias answered 27/2, 2015 at 15:17 Comment(1)
Wacked in an exponentation. Roll back if it's unwanted. By the way, what's your science behind that tolerance?Ruprecht
M
8

The following works for me:

using ::testing::Pointwise;
using ::testing::FloatNear;

auto const max_abs_error = 1 / 1024.f;
ASSERT_THAT(
    test,
    Pointwise(FloatNear(max_abs_error), ref));

Where test and ref are of type std::vector<float>.

Milldam answered 5/8, 2021 at 9:52 Comment(0)
C
4

One approach is to use the googletest rather than googlemock macros, which results in a more compact assert:

#define EXPECT_FLOATS_NEARLY_EQ(expected, actual, thresh) \
        EXPECT_EQ(expected.size(), actual.size()) << "Array sizes differ.";\
        for (size_t idx = 0; idx < std::min(expected.size(), actual.size()); ++idx) \
        { \
            EXPECT_NEAR(expected[idx], actual[idx], thresh) << "at index: " << idx;\
        }

// define expected_array as in the other answer
EXPECT_FLOATS_NEARLY_EQ(impulse, expected_array, 0.001);
Cedillo answered 11/1, 2018 at 15:56 Comment(0)
P
3

Here is one method. First define a matcher outside of the test scope. According to the documentation, the matcher cannot be defined in a class or function . .

MATCHER_P(FloatNearPointwise, tol, "Out of range") {
    return (std::get<0>(arg)>std::get<1>(arg)-tol && std::get<0>(arg)<std::get<1>(arg)+tol) ;
}

Then is can be used with Pointwise int the test . . .

std::vector<float> expected_array({
    0, 0, 0, 1, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
});

EXPECT_THAT(  impulse, Pointwise( FloatNearPointwise(1e-8), expected_array  ) );

But it would be neater if there was a solution that used the builtin FloatNear directly.

Pelagias answered 27/2, 2015 at 18:16 Comment(2)
Note: Pointwise is in testing namespace ::testing::PointwiseLauraine
nit: The string given to MATCHER_P should describe the matcher's passing criteria, not it's failing criteria.Micron

© 2022 - 2024 — McMap. All rights reserved.