Boost logo

Boost Users :

Subject: Re: [Boost-users] whitebox testing with boost unit test framework?
From: Ahmed Badran (ahmed.badran_at_[hidden])
Date: 2011-12-22 14:15:06


On Thu, Dec 22, 2011 at 8:59 AM, Chris Cleeland <chris.cleeland_at_[hidden]>wrote:

> 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.
>

In your header (the class to be tested, you need to forward declare the
test namespace and the tester class, e.g.

// ClassToBeTested.h

// You may be able to generate the forward declaration using a script and
put it in an include file that you
// include here.
namespace test
{
    class TesterOfClassToBeTested;
}

namespace myOtherNamespace { // optional
    class ClassToBeTested
    {
        friend class test::TesterOfClassToBeTested; // here's the one
line :)
        public:
        private:
    };
}

// TesterOfClassToBeTested.cpp

#include "ClassToBeTested.h"

#define foreach BOOST_FOREACH

using namespace std;
using namespace boost;
using namespace stage;

namespace test
{
    class TesterOfClassToBeTested
    {
        public:
        TesterOfClassToBeTested()
        {
        }
        void copy_constructor()
        {
            ClassToBeTested loc2;
            ClassToBeTested loc(loc2);
            BOOST_REQUIRE(loc.locIdStruct == loc2.locIdStruct);
        }
        ~TesterOfClassToBeTested()
        {
        }
        private:
    };
}

BOOST_AUTO_TEST_SUITE(TesterOfClassToBeTested)

struct fixture
{
    test::TesterOfClassToBeTested t;
};

BOOST_FIXTURE_TEST_CASE(copy_constructor, fixture)
{
    t.copy_constructor();
}

BOOST_AUTO_TEST_SUITE_END()

>
>
> 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 mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>



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