googletest
googletest copied to clipboard
Deep comparison between objects
I was interested to see if there are solutions to compare deeply nested structs in C++ where differences in the structs are clearly highlighted on failure.
This is something that Jest in Javascript seems to be doing really well. For example:
const one = {
foo: "bar",
first: {
second: {
third: ["a", "b", "c"]
},
anotherOne: 42
}
}
const two = {
foo: "bar",
first: {
second: {
third: ["a", "b", "d"]
},
anotherOne: 43
}
}
expect(one).toEqual(two);
Will show the following output:
expect(received).toEqual(expected) // deep equality
- Expected - 2
+ Received + 2
Object {
"first": Object {
- "anotherOne": 43,
+ "anotherOne": 42,
"second": Object {
"third": Array [
"a",
"b",
- "d",
+ "c",
],
},
},
"foo": "bar",
}
36 | }
37 |
> 38 | expect(one).toEqual(two);
| ^
39 |
40 | });
41 | });
at Object.<anonymous> (../tests/app.test.ts:38:17)
Test Suites: 1 failed, 1 total
I can very quickly pin point the exact issue due to this intelligent diff. In the terminal this reads even nicer due to better colour coding.
On the other hand if I have this equivalent C++ code:
struct Second {
bsl::vector<char> third;
// Assume operator== is defined
};
struct First {
Second second;
int anotherOne;
// Assume operator== is defined
};
struct Example {
bsl::string foo;
First first;
// Assume operator== is defined
};
TEST(Example, one) {
auto const one = Example{
.foo = "bar",
.first = {
.second = {
.third = {'a', 'b', 'c'}
},
.anotherOne = 42
}
};
auto const two = Example{
.foo = "bar",
.first = {
.second = {
.third = {'a', 'b', 'd'}
},
.anotherOne = 43
}
};
EXPECT_EQ(one, two);
}
I get the following output which is not helpful at all in finding the actual differences.
[ RUN ] Example.one
../src/[...].t.cpp:312: Failure
Expected equality of these values:
one
Which is: { foo: "bar", first: { second: { third: { 'a' (97, 0x61), 'b' (98, 0x62), 'c' (99, 0x63) } }, anotherOne: 42 } }
two
Which is: { foo: "bar", first: { second: { third: { 'a' (97, 0x61), 'b' (98, 0x62), 'd' (100, 0x64) } }, anotherOne: 43 } }
[ FAILED ] Example.one (0 ms)
In larger diffs, this can become really frustrating. Of course, I could define some helper where I dig into the nested structure of the Example
class and print where exactly there are differences.
I was wondering if gtest
could provide some generic solution which, similar to Jest, does that deep and intelligent comparison for me.
JS has the advantage of having a clear interface for type visitation, namely Object properties. That said, IIRC gtest is smart enough to identify when the textual representations are identical, so it's perhaps not too much of a stretch to make it do a "naive" diff of the textual representation as a first improvement in this area.
In #1301 I've raised the issue of factoring out the gtest-printers interface; perhaps there's a case to go further and express it in terms of structured values instead, which may be used for pretty-printing arbitrarily, and doing these kinds of "representation"-level Spot The Difference games.
This is a good feature request, but it is fairly hard to do in C++. I doubt we will have the resources to look into this for a while.
Thanks for taking a look at this.
It would be nice to get updates once someone might be making progress on this feature or features which may make this request easier to solve.
What if you took the string representation that would be printed anyway and just did a text diff on it?