[Test] How to Access Private Data from a Test
In the Bad-Old-Days when I had to roll my own, I would define my tests as methods of a special test class. If those tests needed to access private data in the classes under test, I would declare special test class as a friend of the class under test--one extra statement and everything worked. How do I do that using Boost test (1.58.0) with the AUTO_TEST family of macros? In the labyrinth of macro expansions, I found a struct name with the argument name from BOOST_AUTO_TEST_CASE(), but a friend of that name doesn't work. The ideal case would be to declare the string name in BOOST_AUTO_TEST_SUITE() as a friend so one friend declaration does it all. Alternately, having to declare a separate friend for each BOOST_AUTO_TEST_CASE() would be tedious (especially for large classes), but it would work. At the moment, I'm using the ole private=public trick: #define private public #include "header_under_test" #undef private However, I've already discovered one system header, <sstream>, that won't work with that kludge. There may be others. Is there another workaround for Boost Tests? I can't be the only one who has to access private data in tests. Merrill Cornish
Hi Merrill, Am Donnerstag, 25. Juni 2015, 14:37:30 schrieb Merrill Cornish:
In the Bad-Old-Days when I had to roll my own, I would define my tests as methods of a special test class. If those tests needed to access private data in the classes under test, I would declare special test class as a friend of the class under test--one extra statement and everything worked.
In my opinion, a test should never access private data. But there are times and legacy code where I had no other choice, too.
How do I do that using Boost test (1.58.0) with the AUTO_TEST family of macros?
In the labyrinth of macro expansions, I found a struct name with the argument name from BOOST_AUTO_TEST_CASE(), but a friend of that name doesn't work.
for BOOST_AUTO_TEST_CASE(foo_test) use friend struct ::foo_test; Note the "::" for the global namespace though it might work without.
The ideal case would be to declare the string name in BOOST_AUTO_TEST_SUITE() as a friend so one friend declaration does it all. Alternately, having to declare a separate friend for each BOOST_AUTO_TEST_CASE() would be tedious (especially for large classes), but it would work.
For BOOST_AUTO_TEST_SUITE(test_suite) use friend struct test_suite::foo_test; Rule of thumb: Each SUITE(bar) just add another namespace "bar" into the chain.
At the moment, I'm using the ole private=public trick:
#define private public #include "header_under_test" #undef private
However, I've already discovered one system header, <sstream>, that won't work with that kludge. There may be others.
Won't work with msvc because it mangles the access control specifiers into the symbol name. No luck then...
Is there another workaround for Boost Tests? I can't be the only one who has to access private data in tests.
Been there, done that. Just had to grep the examples out of one of my test suites... Yours, Jürgen -- * Dipl.-Math. Jürgen Hunold ! * voice: ++49 4257 300 ! Fährstraße 1 * fax : ++49 4257 300 ! 31609 Balge/Sebbenhausen * jhunold@gmx.eu ! Germany
On 6/25/2015 3:52 PM, Jürgen Hunold wrote:
In my opinion, a test should never access private data. But there are times and legacy code where I had no other choice, too. The classes I am testing use the PIMPL idiom. Therefore, at a bare minimum, the tests have to access the private pointer in the public class that points to the accompanying private class. Since all of the class's data is inside the private class, it make it extremely difficult to write unit tests that determine if the class state is correct. I see no value in the purist notion that I should have to jump through hundreds of hoops deducing the internal state /just/ so I can say my test never accessed any private data.
On 26/06/2015 09:02, Merrill Cornish wrote:
On 6/25/2015 3:52 PM, Jürgen Hunold wrote:
In my opinion, a test should never access private data. But there are times and legacy code where I had no other choice, too.
The classes I am testing use the PIMPL idiom. Therefore, at a bare minimum, the tests have to access the private pointer in the public class that points to the accompanying private class. Since all of the class's data is inside the private class, it make it extremely difficult to write unit tests that determine if the class state is correct. I see no value in the purist notion that I should have to jump through hundreds of hoops deducing the internal state /just/ so I can say my test never accessed any private data.
That's a misrepresentation of the "purist notion". The idea is that you only test a class through its public methods, because these are the only things that can be observed from "outside", and therefore describes the real behaviour that actually matters. One of the good things that this enables is that it becomes possible to completely change the internal implementation (perhaps to improve performance, perhaps to use a different helper library) and as long as the behaviour remains the same, all the tests continue to pass without changes. Tests that look at internal state are brittle to these sorts of changes, so it becomes harder to tell whether the test breakage is because the refactoring unintentionally changed behaviour or just that the test isn't checking the right thing any more. If it becomes hard to "deduce the internal state" then it's likely that your class has too many responsibilities, and you should consider breaking it up into smaller individually tested components and a top-level composite. (This also increases the chances that one of those components might be usefully reusable elsewhere.)
participants (3)
-
Gavin Lambert
-
Jürgen Hunold
-
Merrill Cornish