Overloading operator== for testing?

1,924 views
Skip to first unread message

Daniel Cheng

unread,
Aug 14, 2012, 7:39:36 PM8/14/12
to Chromium-dev
I'm adding a new struct that's going to be used as a value in lots of maps. I need to compare the maps for equality in several different places in tests and mocks.

As far as I can tell, there are 3 ways to do this:
1) Implement operator==.
EXPECT_EQ(x, y);
EXPECT_CALL(mock, MyFun(y));

2) Add a function called AreMapsEqual.
EXPECT_TRUE(AreMapsEqual(x, y));
EXPECT_CALL(mock, MyFun(Truly(IsMapEqualTo(y)));
(this variation has the additional disadvantage that failures don't automatically print values)

3) Implement a Gmock matcher MapMatcherEq.
EXPECT_THAT(x, MyCustomMapEq(y));
EXPECT_CALL(mock, MyFun(MyCustomMapEq(y));

Would it be permissible to overload operator== in this case? I feel like the == variation results in the clearest test code--or is there a better way to do this?

Ryan Sleevi

unread,
Aug 14, 2012, 7:45:38 PM8/14/12
to dch...@chromium.org, Chromium-dev
On Tue, Aug 14, 2012 at 4:39 PM, Daniel Cheng <dch...@chromium.org> wrote:
> I'm adding a new struct that's going to be used as a value in lots of maps.
> I need to compare the maps for equality in several different places in tests
> and mocks.
>
> As far as I can tell, there are 3 ways to do this:
> 1) Implement operator==.
> EXPECT_EQ(x, y);
> EXPECT_CALL(mock, MyFun(y));
>
> 2) Add a function called AreMapsEqual.
> EXPECT_TRUE(AreMapsEqual(x, y));
> EXPECT_CALL(mock, MyFun(Truly(IsMapEqualTo(y)));
> (this variation has the additional disadvantage that failures don't
> automatically print values)

Using ASSERT_PRED2(AreMapsEqual, x, y) will print out x and y and have
all the other behaviours of EXPECT_TRUE

That said, if you're going to be using GMock and EXPECT_CALL, it would
seem that a GMock predicate (option 3) is really the best way .

>
> 3) Implement a Gmock matcher MapMatcherEq.
> EXPECT_THAT(x, MyCustomMapEq(y));
> EXPECT_CALL(mock, MyFun(MyCustomMapEq(y));
>
> Would it be permissible to overload operator== in this case? I feel like the
> == variation results in the clearest test code--or is there a better way to
> do this?

It results in the cleanest test code, but leaves subtlety for
production code that has to be reasoned carefully about. I think 3 is
perhaps the best way here, provided GMock hasn't totally been banned
:)

Daniel Cheng

unread,
Aug 14, 2012, 8:09:51 PM8/14/12
to rsl...@chromium.org, Chromium-dev
What sort of subtleties would this cause in production code? Production code won't ever compare the structs (or their containers) for equality.

I have several reservations with 3:
- if (Matches(ObjectIdStateMapEq(expected))(actual)) looks odd (to me)
- 80 character limit + long custom matcher name makes reading expectations pretty annoying. In my case, I'm going to have to define three custom matchers: InvalidationStateEq, ModelTypeStateMapEq, and ObjectIdStateMapEq. I think I can probably cheat and reuse the Eq() name for the matcher factory functions, but I'm not sure how people would feel about that since it doesn't seem to be something that's generally done.
- General desire to not reimplement things that already work just fine. In this case, I can just use std::equal() to compare the two maps but it seems silly... especially since I have to do the same thing in multiple matchers.

Daniel

Victor Khimenko

unread,
Aug 15, 2012, 4:27:09 AM8/15/12
to dch...@chromium.org, rsl...@chromium.org, Chromium-dev
Note that you can implement it in some testing namespace - then production code will not be able to accidentally call it. Or you can even implement in your tests...
 
I have several reservations with 3:
- if (Matches(ObjectIdStateMapEq(expected))(actual)) looks odd (to me)
- 80 character limit + long custom matcher name makes reading expectations pretty annoying. In my case, I'm going to have to define three custom matchers: InvalidationStateEq, ModelTypeStateMapEq, and ObjectIdStateMapEq. I think I can probably cheat and reuse the Eq() name for the matcher factory functions, but I'm not sure how people would feel about that since it doesn't seem to be something that's generally done.
- General desire to not reimplement things that already work just fine. In this case, I can just use std::equal() to compare the two maps but it seems silly... especially since I have to do the same thing in multiple matchers.

Daniel

--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev

Reply all
Reply to author
Forward
0 new messages