class design: where to put debug purpose utility class?

1

1230987za

Hi,

Let's say I have the following class:

class foo {
public:
foo();
void addItem(int item);

private:
int* items;
};

I want to write a unit test program to test foo::addItem(), to do that
the test program needs to know the contents of foo::items.

So I can add one more public function to class foo:
int* getItems();

But suppose in my case, the client code of class foo does not need
getItems() at all, this function serves only for test in this case.

So I am considering to have a separate class fooTest and this class is
a friend class of class foo so that it has an API to retrieve all
private data of foo.

I believe this works, but I am wondering if there is better solution.
Basically my goals are:
1. I do not want the class to be bloated with a lot of API which only
serve for test purpose
2. I want the function class to be independent from test class

Thanks a lot.
 
K

Kai-Uwe Bux

Hi,

Let's say I have the following class:

class foo {
public:
foo();
void addItem(int item);

private:
int* items;
};

I think you oversimplified your example: any implementation off addItem()
will do since whatever it does, no client will be able to tell as the class
does not provide any way of using the private data. Without observable
semantics, neither does the class serve a purpose nor is there anything to
test.

I want to write a unit test program to test foo::addItem(), to do that
the test program needs to know the contents of foo::items.

So I can add one more public function to class foo:
int* getItems();

But suppose in my case, the client code of class foo does not need
getItems() at all, this function serves only for test in this case.

Well, client code will have _some_ uses of the class. Such uses should
provide meaningfull ways of testing the observable behavior of the class,
i.e., you should be able to write tests that make sure the class keeps its
contractual obligations. That is where I would start. Otherwise, you end up
testing implementation details. Since those might change, I don't think
that client or outside test code have any business knowing about them.


[snip]


Best

Kai-Uwe Bux
 
G

Greg Herlihy

Let's say I have the following class:

class foo {
public:
    foo();
   void addItem(int item);

private:
   int* items;
};

I want to write a unit test program to test foo::addItem(), to do that
the test program needs to know the contents of foo::items.

No, the unit test program has to confirm only that addItem() did what
it was supposed to do (or more formally, that the functions's
"postcondition" has been fulfilled after the call). Moreover, testing
addItem()'s postconditions is done solely from a client's point of
view. A unit test has no special access to the internals of the
interface being tested - nor does it have any knowledge of the
inteface's implementation.

So in this example, a unit test would confirm that addItem() worked by
calling other -public- routines in foo's interface - that would have
beeen affected by the addItem() call. For example, if foo had a size()
method, a unit test would might call size() before calling addItem(),
save the result, then call adItem() and then call size() again, and
confirm that the size() of foo has increased by one.
So I can add one more public function to class foo:
  int* getItems();

But suppose in my case, the client code of class foo does not need
getItems() at all, this function serves only for test in this case.

If the client does not need a getItems() method then there is no
reason to add one to foo's interface. A unit test should test only the
public routines an interface - and use only the public methods of the
interface (that is, the one available to all clients) to do so. A unit
test should not have special knowledge of the internals of the
interface's implementation.

After all, if there is no way for the client to tell whether addItem()
did anything or not, then there would be no reason for the client to
call addItem() in the first place. Because from the client's point of
view - whether addItem() is called or not - makes absolutely no
difference, so why bother calling addItem() at all?
So I am considering to have a separate class fooTest and this class is
a friend class of class foo so that it has an API to retrieve all
private data of foo.

Giving the test access to foo's private data would make the test
dependent on those implementation details - exactly what an unit test
must avoid. For one, if the unit test tests only the public interface,
then the programmer is free to replace the entire implementation of
"foo" without breaking (or having to rewrite ) the test. The unit test
can also confirm that any such refactoring has not changed foo's
behavior in any way that would affect clients of foo.
I believe this works, but I am wondering if there is better solution.
Basically my goals are:
1. I do not want the class to be bloated with a lot of API which only
serve for test purpose

There should not be any code added to foo's public API for unit
testing purposes.
2. I want the function class to be independent from test class

Yes, the unit test should be completely independent from the interface
being tested (in other words, the unit test should just be another
client of foo - and nothing more).

Greg
 
J

Joe Greer

There should not be any code added to foo's public API for unit
testing purposes.


Yes, the unit test should be completely independent from the interface
being tested (in other words, the unit test should just be another
client of foo - and nothing more).

I wouldn't necessarily disagree with this, but I seem to have a lot of classes whose primary goal is a side
effect. For example a writer to a file. By design, there really isn't any feedback to the client of the
class, it just works or throws. If I just treat things as a normal user, I have no way of knowing directly
if the data made it to the file or if there was a error that wasn't reported properly. How do you usually
test such cases or is that another class of test that isn't called a 'unit test'?

joe
 
S

SeanW

@a9g2000prl.googlegroups.com:





I wouldn't necessarily disagree with this, but I seem to have a lot of classes whose primary goal is a side
effect. For example a writer to a file. By design, there really isn't any feedback to the client of the
class, it just works or throws. If I just treat things as a normal user, I have no way of knowing directly
if the data made it to the file or if there was a error that wasn't reported properly. How do you usually
test such cases or is that another class of test that isn't called a 'unit test'?

I would just reach around in that case:

test_object.append("some.file", "SOME-STRING");
assert(system("tail -n 1 some.file | grep -q '^SOME-STRING$'") ==
0);

Or something along those lines.

Sean
 
J

Joe Greer

I would just reach around in that case:

test_object.append("some.file", "SOME-STRING");
assert(system("tail -n 1 some.file | grep -q '^SOME-STRING$'") ==
0);

Or something along those lines.

Yes. but that wouldn't be using my class' public interface. I can see a
lot of different ways to check it outside the class, but is that still
within Greg's definition of a unit test?

joe
 
J

James Kanze

Yes. but that wouldn't be using my class' public interface. I
can see a lot of different ways to check it outside the class,
but is that still within Greg's definition of a unit test?

I don't see why not. The "public" interface of the class is
what is visible from outside the class. Data written a file is
(hopefully) visible, and thus part of the public
interface---part of the post-condition. (I have some cases
where the "post-condition" is a core dump; I also have unit
tests which verify this.)
 
J

Joe Greer

I don't see why not. The "public" interface of the class is
what is visible from outside the class. Data written a file is
(hopefully) visible, and thus part of the public
interface---part of the post-condition. (I have some cases
where the "post-condition" is a core dump; I also have unit
tests which verify this.)


Fair enough, This is what I actually assumed, but I just wanted to be clear
on the definitions in case I was missing something.

joe
 
G

Greg Herlihy

I wouldn't necessarily disagree with this, but I seem to have a lot of classes whose primary goal is a side
effect.  For example a writer to a file.  By design, there really isn't any feedback to the client of the
class, it just works or throws.  If I just treat things as a normal user, I have no way of knowing directly
if the data made it to the file or if there was a error that wasn't reported properly.  How do you usually
test such cases or is that another class of test that isn't called a 'unit test'?

Even though the unit test should not call any non-public methods of
the interface being tested - there is no reason why the unit test
should not call other functions, functions that do not belong to the
interface being tested if necessary to verify that a function's
postconditions have been met.

So in this example, the "right" way to verify the interface function
that writes data to a file - would depend (as always) on the exact
guarantee (in the form of postconditions) that the function called,
has made to its clients; (assuming of course the client had first met
all of the function's "preconditions" before the function call).

Therefore, the question is whether the function called, promises to
have written certain information to a file by the time the function
returns. If the function makes such a detailed promise, then the unit
test should indeed open the file (by using standard I/O routines),
read the the file's contents, and verify that they match the content
in the form promised by the interface.

The more likely scenario, however, is that the function being tested
makes a less specific promise, perhaps promising only to store the
user-provided data "in a safe place" (with the implicit promise that
the data stored could be subsequently retrieved intact by the client).
In this case, the unit test should not examine the contents of the
file. In fact, client should not even know that this file exists -
because the interface never promised that the "safe place" was
necessarily in a file. Instead, the unit test has to verify only that
the data has been stored safely enough to be retrievable. So the unit
test would verify the function's postconditions by attempting to
retrieve the data (through the interface's public methods) - and once
the data has been retrieved - comparing it against a copy of the
original data passed to the function call.

Essentially, all unit test verifications will fall roughly into one of
these two categories: either the postconditions will be detailed
enough to be verifiable by external routines - or nonspecific enough
that the public interface will have to offer methods that can be used
for verification. Because, as I noted in my previous post - every time
that a client calls a function, the client "wants" something to happen
(otherwise, why bother?). So one of the primary benefits of writing
unit tests (and the reason why they prove so useful) is that they
reconcile the client's expectations with the implementation's own
guarantees. Otherwise, without a clear accounting on each side, it is
all too easy for the client to make assumptions about an interface
that its implementation never had any intention of guaranteeing. So,
by eliminating discrepancies between what a client expects and what an
implementation delivers - a sizable number of bugs can be avoided.

Greg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top