Re: class design: where to put debug purpose utility class?
On Jun 27, 5:56 am, Joe Greer <jgr...@doubletake.com> wrote:
Greg Herlihy <gre...@mac.com> wrote in news:317895b6-3422-489c-a280-4c502=
There should not be any code added to foo's public API for unit
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).
I wouldn't necessarily disagree with this, but I seem to have a lot of cl=
asses 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 use=
r, I have no way of knowing directly
if the data made it to the file or if there was a error that wasn't repor=
ted properly. How do you usually
test such cases or is that another class of test that isn't called a 'uni=
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.