Boost logo

Boost Users :

Subject: Re: [Boost-users] whitebox testing with boost unit test framework?
From: Chris Cleeland (chris.cleeland_at_[hidden])
Date: 2011-12-22 11:59:55


Thanks to all for the suggestions! You are correct that I'm testing
"legacy" code, though in this particular case the legacy code is
completely open for change. But, I need unit tests before I go
mucking about so I know that I haven't made things any worse than they
are.

On Wed, Dec 21, 2011 at 7:04 PM, Ahmed Badran <ahmed.badran_at_[hidden]> wrote:
> That is what I've come to accept as probably the cleanest possible solution
> without hacking/redefining "private"/"protected" in production vs. test code
> (even though it's far from what I would call elegant).
> For a class I essentially create a friend in a completely different "test"
> namespace, the unit tests go in that namespace and are linked against the
> object files to test them and validate class internals/invariants. The
> shipping code (headers) always have the 'missing' friend declarations, but
> as I said it's a 1 line that I've gotten to accept as the least ugly
> solution until I come across something that's more elegant.

For some reason I'm having difficulties implementing this suggestion.

The "legacy" code lives in a namespace, e.g.,

// ClassToBeTested.hh
namespace mycompany {
namespace internal {
class ClassToBeTested { ... };
} // namespace internal
} // namespace mycompany

If I understand the suggestion, I think I want to put the testing in a
different namespace, e.g.,

// test_ClassToBeTested.cxx
namespace mycompany {
namespace internal {
namespace test {
  // here lies the boost unit test stuff that I create
  struct ClassToBeTested_suite_fixture { ... };
  BOOST_FIXTURE_TEST_SUITE( ClassToBeTested_suite,
ClassToBeTested_suite_fixture )
  ... here lie unit tests...
  BOOST_AUTO_TEST_SUITE_END()
} } }

So, in the declaration for ClassToBeTested, I should have something like

class ClassToBeTested {
public:
  // public interface
protected:
  // protected members/methods
  friend class mycompany::internal::test::ClassToBeTested_suite_fixture;
};

When I compile, the compiler complains that it does not know about
namespace 'test'

]$ clang++ namespace_test.cxx
namespace_test.cxx:4:46: error: no member named 'test' in namespace
'mycompany::internal'
         friend class
::mycompany::internal::test::ClassToBeTested_suite_fixture;
                      ~~~~~~~~~~~~~~~~~~~~~~~^
namespace_test.cxx:6:8: error: expected external declaration
   } } }
       ^
2 errors generated.

The only way I've found around this is to forward declare
ClassToBeTested_suite_fixture in the ClassToBeTested header, e.g.,

// ClassToBeTested.hh
namespace mycompany {
namespace internal {
namespace test { class ClassToBeTested_suite_fixture; }
class ClassToBeTested { ... };
} // namespace internal
} // namespace mycompany

Is this the technique that you use? I wonder, because it's more than
one lane and still intrusive, and I'm wondering if I'm missing
something.

-- 
Chris Cleeland

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net