473,395 Members | 1,745 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Testing protected or private functionality?

I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?

Apr 17 '06 #1
12 3106
Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in
C++". I just decided I wanted to place some member functions out from
public into a protected scope. Problem is that my tests want to
access those functions...bummer. What have other people done when
faced with this problem or just the general problem of testing
functionality encapsulated in a private manner?


Duplicate the testing functionality in the class and #ifdef it so that
the final product doesn't have it:

class A {
void someprivatefunction(int);
public:
#ifdef DO_TEST
void test() {
someprivatefunction(42);
assert(somepostcondition);
}
#endif
};

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 17 '06 #2
Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?

You could either make the test class a friend, or refactor the private
methods into another object and test that.

--
Ian Collins.
Apr 17 '06 #3

Ian Collins wrote:
Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?

You could either make the test class a friend, or refactor the private
methods into another object and test that.


That would work ok for privates, an exposed pimpl of sorts, but for
protected members it could be a bit problematic.

Apr 17 '06 #4
Noah Roberts wrote:
Ian Collins wrote:
Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?


You could either make the test class a friend, or refactor the private
methods into another object and test that.

That would work ok for privates, an exposed pimpl of sorts, but for
protected members it could be a bit problematic.

Which option and how would it be problematic?

--
Ian Collins.
Apr 17 '06 #5
Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?


There's a spectrum of answers, depending on whether tests are written before
or after the tested code.

Under pure Test Driven Development, you write failing test cases, then write
the code to pass them. Then you refactor the code to make methods generally
shorter and less redundant.

At refactor time, methods should Extract Method their common code into
private methods that only they call. Tests will still cover these private
methods' behaviors. The original test cases that created these behaviors
will still defend the behaviors against change.

As a module grows under test, programmers might need to add behavior
directly to these private methods. At this time, they can write public
wrappers for the methods, or make the methods public. If a test case can
easily use a method, clients ought to be allowed to use it the same way,
too.

If the method is not yet ready for re-use by production code, the programmer
can supply a sternly-worded comment. Static type checking becomes less
important as programmers invest in test cases for run-time checking.

When programmers add new tests to legacy code, they should start low, to
test soft targets and begin to make the code ready for refactoring and more
tests. Low targets are typically private. I publish them like this:

#ifdef _DEBUG
# define DEBUG_(X_) X_
#else
# define DEBUG_(X_)
#endif

....

private:
DEBUG_(public:)
void secretlyTestMe();

Now a test case can grab secretlyTestMe(), but when we compile in release
mode we still get the static type checking on this class's private things.
(_DEBUG is often defined when the Standard NDEBUG is not, and the DEBUG_()
macro now becomes useful for other optional code, too.)

Some systems can make the test case a friend. I prefer test runners like
CppUnitLine that use a Test Collector to dynamically generate a class for
each test case. This thing's name is difficult to type, and classes should
have more than one test case. Listing them in each tested class is not just
a pain, it's also an invitation for cascading recompiles.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 17 '06 #6

Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?


Thanks for the ideas. After looking at the matter and the responses I
think I favor something like this:

class Test { public: virtual void test() = 0; };
class TOut
{
class TestTout;
protected:
void print(std::string x) { cout << x; }
public:
static std::auto_ptr<Test> test();
};

class TOut::TestTout : public Test
{
TOut tout;
public:
void test() { tout.print("TEST"); }
};

std::auto_ptr<Test> TOut::test() { return std::auto_ptr<Test>(new
TOut::TestTout()); }

int main()
{
std::auto_ptr<Test> t = TOut::test();
t->test();

int x;
cin >> x;
}

This still allows me to keep the test and the subject pretty separated
(can declare the two in separate headers) and gives me the access I
need. I have to declare the test harness in the class I am testing and
provide a factory for it but that is pretty minor cost.

Apr 17 '06 #7
Noah Roberts wrote:
Noah Roberts wrote:
I'm using a simple unit test architecture I found in "Thinking in C++".
I just decided I wanted to place some member functions out from public
into a protected scope. Problem is that my tests want to access those
functions...bummer. What have other people done when faced with this
problem or just the general problem of testing functionality
encapsulated in a private manner?

Thanks for the ideas. After looking at the matter and the responses I
think I favor something like this:

class Test { public: virtual void test() = 0; };
class TOut
{
class TestTout;
protected:
void print(std::string x) { cout << x; }
public:
static std::auto_ptr<Test> test();
};

class TOut::TestTout : public Test
{
TOut tout;
public:
void test() { tout.print("TEST"); }
};

std::auto_ptr<Test> TOut::test() { return std::auto_ptr<Test>(new
TOut::TestTout()); }

int main()
{
std::auto_ptr<Test> t = TOut::test();
t->test();

int x;
cin >> x;
}

This still allows me to keep the test and the subject pretty separated
(can declare the two in separate headers) and gives me the access I
need. I have to declare the test harness in the class I am testing and
provide a factory for it but that is pretty minor cost.

Have you looked at unit test frameworks like CppUnitLite or CppUnit?

--
Ian Collins.
Apr 17 '06 #8
Noah Roberts wrote:
class Test { public: virtual void test() = 0; };


This solution is way too complicated for the simple problem.

"private" is not some hallowed sacred concept. It is a tool, to be picked up
and put down at need.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 18 '06 #9
Ian Collins wrote:
Have you looked at unit test frameworks like CppUnitLite or CppUnit?


He's not implementing the framework. (Hard to tell, but true.) He's using
main() as the test case, and showing how he can make a chain of permitted
access between main() and the private function.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 18 '06 #10

Phlip wrote:
Noah Roberts wrote:
class Test { public: virtual void test() = 0; };


This solution is way too complicated for the simple problem.

"private" is not some hallowed sacred concept. It is a tool, to be picked up
and put down at need.


Actually, it is very simple and not prone to one error I want to
totally avoid:

class X
{
protected:
#ifdef DEBUG
public:
#endif
int f() const;
};

#ifdef DEBUG
class XTest : public Test
{
X x;
public:
void run() { test(x.f() == 5); }
};
#endif

.... somewhere else in someone else's code....

X x;
x.f();

Now the system compiles and runs in debug mode only...a stupid error
for sure, but one that could cost a lot of time right before product
release that would require going through the testing phaze again. If
you hire inexperienced programmers, like interns, they might very well
miss something like that...hell, I could do it on a Monday. That just
seems to introduce too much confusion to me.

On the other hand, having the class return an inner test object that no
client knows the interface for (unless they include test headers)
offers a bit more abstraction and protection. Plus, there is no
reason, other than testing, for someone to make calls to the test
interface...but someone might think they want access to a member that
is public in debug build as it actually acomplishes something.

I also have a bit of a thing against the preprocessor. I like to avoid
using it when I can and use the language and classes instead.

Apr 18 '06 #11

Ian Collins wrote:
Have you looked at unit test frameworks like CppUnitLite or CppUnit?


I've started using boost test at home, but I don't have the option at
work. I kind of shuffled in the testing framework from Thinking in
C++. Very simplistic but it meets my immediate needs and it will be
easy to replace if I am told to.

Apr 18 '06 #12
Noah Roberts wrote:
... somewhere else in someone else's code....

X x;
x.f();

Now the system compiles and runs in debug mode only...a stupid error
for sure, but one that could cost a lot of time right before product
release that would require going through the testing phaze again.
This is a different consideration. But first: I use the DEBUG trick ONLY
because I'm working a legacy project, with tests written long after the
tested code.

Regardless whether I do or not, our build script builds and tests each of
the Debug version, the Profiling version and the Release version each time
anyone submits code. If they break any of those builds they get an e-mail.

(They get the e-mail anyway; that's a small risk they might stop reading
it!;)
If
you hire inexperienced programmers, like interns, they might very well
miss something like that...hell, I could do it on a Monday. That just
seems to introduce too much confusion to me.
That's what pair programming and other code reviews are for.
I also have a bit of a thing against the preprocessor. I like to avoid
using it when I can and use the language and classes instead.


Use the preprocessor for...

- token pasting
- conditional compilation
- stringerization

Then don't abuse those abilities. ;-)

If you write tests at the same time as the tested code, your interface
should be a little wider, and a little healthier. This is not the same thing
as adding extra Get methods for your private variables. And no
private-but-public tricks, either.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 18 '06 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Fabian | last post by:
Can IE6 be set to have js disabled? If not, what is teh simplest way to check for non-js functionality? -- -- Fabian Visit my website often and for long periods! http://www.lajzar.co.uk
5
by: Christian Meier | last post by:
Hi dear programmers I looked for the difference between private and protected inheritance, but couldn't find anything. Here is my sample code: #include <iostream> using std::cout; using...
2
by: MJ | last post by:
Hi I have a following sample code class base and class derived. I have inherited the base class as private and tried to compile the code its giving an error "conversion from 'class derived *' to...
8
by: __PPS__ | last post by:
Hello everybody, today I had another quiz question "if class X is privately derived from base class Y what is the scope of the public, protected, private members of Y will be in class X" By...
4
by: Gawel | last post by:
Let say I have: public class Class1 { protected int _counter; public void MakeSomethingWithCounter() { _counter = 10; or <--------------------------which way is morr accurate ?
11
by: Kevin Prichard | last post by:
Hi all, I've recently been following the object-oriented techiques discussed here and have been testing them for use in a web application. There is problem that I'd like to discuss with you...
3
by: jagadidishrout83 | last post by:
http://img398.imageshack.us/img398/5599/preseiw4.jpg
8
by: Mayur H Chauhan | last post by:
All, For my knowledge, if I declare Class as follow, then it thows compilation error. Protected Class Book End Class Even same for...
14
by: Karsten Dambekalns | last post by:
Hi. Thomas Mlynarczyk wrote: Why do you want them to be private in the first place? I have yet to see code where this really makes sense... And if it does, then the external public API is...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.