FRIEND_TEST_ALL_PREFIXES vs Peer classes

128 views
Skip to first unread message

Jochen Eisinger

unread,
Jul 31, 2018, 1:49:25 PM7/31/18
to cxx, Martin Kreichgauer
Hey,

the following question came up in a review. Should we prefer introducing Peer classes as described in https://abseil.io/tips/135 over usage of FRIEND_TEST_ALL_PREFIXES (for the reasons mention in said blog post), or should we continue using FRIEND_TEST_ALL_PREFIXES because consistency.

best
-jochen

Daniel Cheng

unread,
Jul 31, 2018, 1:56:47 PM7/31/18
to Jochen Eisinger, cxx, mart...@google.com
I think using adding a helper class that's a friend of the tested class is a lot cleaner than using FRIEND_TEST / FRIEND_TEST_ALL_PREFIXES, since the list of friend tests can get quite long (and it introduces this weird coupling of production code on test code). I think consistency won't be too bad: certainly, an individual test file should be internally consistent, but using this in new test files seems like a good idea to me.

I wonder why their recommendation steers clear of just having the class friend the test fixture: I guess the idea is the helper class could be shared between multiple unittest modules that way?

Daniel

--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CALjhuifVPTPNYaKK20o4runexdpwnzFWjix9T%2B-s2yOHL_ETzw%40mail.gmail.com.

Martin Kreichgauer

unread,
Jul 31, 2018, 2:01:27 PM7/31/18
to dch...@chromium.org, joc...@chromium.org, c...@chromium.org
On Tue, Jul 31, 2018 at 10:56 AM Daniel Cheng <dch...@chromium.org> wrote:
I think using adding a helper class that's a friend of the tested class is a lot cleaner than using FRIEND_TEST / FRIEND_TEST_ALL_PREFIXES, since the list of friend tests can get quite long (and it introduces this weird coupling of production code on test code). I think consistency won't be too bad: certainly, an individual test file should be internally consistent, but using this in new test files seems like a good idea to me.

I wonder why their recommendation steers clear of just having the class friend the test fixture: I guess the idea is the helper class could be shared between multiple unittest modules that way?

The Google style guide does say "In some cases it may be useful to make a unittest class a friend of the class it tests.". IMHO, it depends on the circumstances. A test peer can make it more obvious, which implementation details are being exposed, and it can be reused between different test fixtures.

Peter Kasting

unread,
Jul 31, 2018, 2:18:01 PM7/31/18
to Daniel Cheng, Jochen Eisinger, cxx, mart...@google.com
On Tue, Jul 31, 2018 at 10:56 AM Daniel Cheng <dch...@chromium.org> wrote:
I think using adding a helper class that's a friend of the tested class is a lot cleaner than using FRIEND_TEST / FRIEND_TEST_ALL_PREFIXES, since the list of friend tests can get quite long (and it introduces this weird coupling of production code on test code). I think consistency won't be too bad: certainly, an individual test file should be internally consistent, but using this in new test files seems like a good idea to me.

I wonder why their recommendation steers clear of just having the class friend the test fixture: I guess the idea is the helper class could be shared between multiple unittest modules that way?

Your comments sound like they still center on the idea that the test tests private details of the original class, and just looks at differences in how that could be made to occur.

It sounds to me like instead this TOTW is trying to request that tests not access implementations' private methods/variables, and that instead the class be structured in such a way that the public API is sufficient for the relevant testing.  This encourages authors to test the publicly-visible behavior instead of the fine-grained details of how that public behavior is implemented at a low level, thus making tests less brittle.

PK

Daniel Cheng

unread,
Jul 31, 2018, 2:22:42 PM7/31/18
to Peter Kasting, Jochen Eisinger, cxx, mart...@google.com
I agree that not accessing the private details is better, when possible. But in the case that's not possible, using a friend class seems strictly better than FRIEND_TEST / FRIEND_TEST_ALL_PREFIXES.

Daniel

Peter Kasting

unread,
Jul 31, 2018, 2:26:09 PM7/31/18
to Daniel Cheng, Jochen Eisinger, cxx, mart...@google.com
On Tue, Jul 31, 2018 at 11:22 AM Daniel Cheng <dch...@chromium.org> wrote:
I agree that not accessing the private details is better, when possible. But in the case that's not possible, using a friend class seems strictly better than FRIEND_TEST / FRIEND_TEST_ALL_PREFIXES.

I think reasonable arguments could be made for either position; to me, if there's anything to debate here, it's more the core idea of "try as hard as possible to not test private details", which is very much not the current philosophy in Chrome code.  The specifics of how to test private details if you decide to do so feels a little more bikeshed-y.

PK 

Daniel Cheng

unread,
Jul 31, 2018, 2:35:35 PM7/31/18
to Peter Kasting, Jochen Eisinger, cxx, mart...@google.com
FRIEND_TEST_ALL_PREFIXES is overused and clutters non-test code. There are 82 files with 10+ instances FRIEND_TEST_ALL_PREFIXES, with the record being 50 in this file: https://cs.chromium.org/chromium/src/components/safe_browsing/db/v4_store.h?rcl=017b67704ac5c26b60a3674866a2325c8db020cd&l=230

Daniel

Martin Kreichgauer

unread,
Jul 31, 2018, 2:36:04 PM7/31/18
to pkas...@google.com, dch...@chromium.org, joc...@chromium.org, c...@chromium.org
I think everyone agrees that testing private implementation details should be avoided. Still, the ToTW IMO makes a strong case that the difference between friending a peer class (or maybe a test fixture) and using FRIEND_TEST is not just bike shedding. Almost half of the post deals with that question.

Peter Kasting

unread,
Jul 31, 2018, 2:51:53 PM7/31/18
to mart...@google.com, Daniel Cheng, Jochen Eisinger, cxx
On Tue, Jul 31, 2018 at 11:36 AM Martin Kreichgauer <mart...@google.com> wrote:
I think everyone agrees that testing private implementation details should be avoided.

Given the current state of Chromium code, I don't believe it's true that everyone agrees on this -- or we wouldn't be doing it so pervasively and consistently, including in new changes I review.

I think it is vastly more beneficial to our testability to actually get everyone to agree on this than to fix the issue of peer classes versus FRIEND_TEST.  The latter is a nice-to-have, the former is more must-have; and it's something that is not called out in our style guides or Dos-and-Don'ts page, or recommended to new team members anywhere.

PK

Antoine Labour

unread,
Jul 31, 2018, 4:23:13 PM7/31/18
to Peter Kasting, mart...@google.com, Daniel Cheng, Jochen Eisinger, cxx
On Tue, Jul 31, 2018 at 11:51 AM 'Peter Kasting' via cxx <c...@chromium.org> wrote:
On Tue, Jul 31, 2018 at 11:36 AM Martin Kreichgauer <mart...@google.com> wrote:
I think everyone agrees that testing private implementation details should be avoided.

Given the current state of Chromium code, I don't believe it's true that everyone agrees on this -- or we wouldn't be doing it so pervasively and consistently, including in new changes I review.

Both black-box testing and white-box testing have their uses and trade-offs. I don't think it has to be one or the other.
Some complex classes may have internal invariants, and it is very reasonable and desirable to verify that those invariants are conserved when operating on the class, in unit tests. That requires exposing those invariants to the test, one way or the other.

Antoine
 

I think it is vastly more beneficial to our testability to actually get everyone to agree on this than to fix the issue of peer classes versus FRIEND_TEST.  The latter is a nice-to-have, the former is more must-have; and it's something that is not called out in our style guides or Dos-and-Don'ts page, or recommended to new team members anywhere.

PK

--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.

Jochen Eisinger

unread,
Aug 1, 2018, 6:11:38 AM8/1/18
to Antoine Labour, Peter Kasting, mart...@google.com, Daniel Cheng, cxx
so... what's the conclusion? Assuming that a given test wants to look at internal state, go with consistency, or go with the Peer pattern?

Sadrul Chowdhury

unread,
Aug 1, 2018, 11:28:56 AM8/1/18
to joc...@chromium.org, Antoine Labour, Peter Kasting, mart...@google.com, Daniel Cheng, c...@chromium.org
A few components in the tree use the peer-pattern, where the peers have a TestApi suffix. The usage is not super-consistent though (e.g. some are in a 'test' namespace, some not, some parts of the code in these components still use FRIEND_ macros). But I personally prefer this peer-pattern over using FRIEND_ in new code for the same reasons mentioned upthread.

Sadrul

Albert J. Wong (王重傑)

unread,
Aug 1, 2018, 1:24:10 PM8/1/18
to Sadrul Chowdhury (Google Drive), Jochen Eisinger, Antoine Labour, Peter Kasting, mart...@google.com, Daniel Cheng, c...@chromium.org
My vote is go for peer class rather than a forest of FRIEND_BLAHDEBLAH if the forest starts getting anywhere near big, but that it's okay to exercise judgement in this particular case.

Rigid consistency here doesn't seem to have huge benefits.

-Albert


Victor Costan

unread,
Aug 1, 2018, 9:59:33 PM8/1/18
to ajw...@chromium.org, Sadrul Chowdhury, Jochen Eisinger, pi...@google.com, pkas...@google.com, mart...@google.com, Daniel Cheng, cxx
I think new code should use Peer classes.

As https://abseil.io/tips/ describes, the internal version of Abseil's tips of the week is referenced in Google's code reviews and has quite a bit of weight. While not the main subject of this thread, I think we should consider all the tips there and adopt them as strong recommendations, when they don't conflict with our own style guide and wisdom.

Asides from exposing a narrower interface to tests (which I really like), a hypothetical future where we get rid of all the FRIEND_ macros means we don't have to expose gtest_prod.h to non-test components. While I don't think these advantages are strong enough to migrate the whole codebase now, I do think they're significant enough to be worth adopting for new code.

    Victor


Jeremy Roman

unread,
Aug 7, 2018, 10:20:45 AM8/7/18
to Victor Costan, Albert J. Wong (王重傑), Sadrul Chowdhury, Jochen Eisinger, Antoine Labour, Peter Kasting, mart...@google.com, Daniel Cheng, cxx
I agree with the totw (public members > peer classes > friending tests), but I'm not sure that I'd fight particularly hard for it in code review, especially while it's small and there's a small number of such tests.

Reply all
Reply to author
Forward
0 new messages