class design: where to put debug purpose utility class?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • 1230987za@gmail.com

    class design: where to put debug purpose utility class?

    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.
  • Kai-Uwe Bux

    #2
    Re: class design: where to put debug purpose utility class?

    1230987za@gmail .com wrote:
    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

    Comment

    • James Kanze

      #3
      Re: class design: where to put debug purpose utility class?

      On Jun 27, 4:15 pm, Joe Greer <jgr...@doublet ake.comwrote:
      SeanW <sean_woolc...@ yahoo.comwrote
      innews:59098432-24aa-4161-9493-de4ced3f77a1@l4 2g2000hsc.googl egroups.com:
      On Jun 27, 8:56 am, Joe Greer <jgr...@doublet ake.comwrote:
      Greg Herlihy <gre...@mac.com wrote in
      news:317895b6-3422-489c-a280-4c502ab5ec62
      @a9g2000prl.goo glegroups.com:
      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).
      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.app end("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?
      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.)

      --
      James Kanze (GABI Software) email:james.kan ze@gmail.com
      Conseils en informatique orientée objet/
      Beratung in objektorientier ter Datenverarbeitu ng
      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

      Comment

      • Joe Greer

        #4
        Re: class design: where to put debug purpose utility class?

        James Kanze <james.kanze@gm ail.comwrote in
        news:34c5dabd-6dba-4681-9e5d-6df5905a5e9a@k3 0g2000hse.googl egroups.com:
        >
        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

        Comment

        • Greg Herlihy

          #5
          Re: class design: where to put debug purpose utility class?

          On Jun 27, 5:56 am, Joe Greer <jgr...@doublet ake.comwrote:
          Greg Herlihy <gre...@mac.com wrote in news:317895b6-3422-489c-a280-4c502ab5ec62
          @a9g2000prl.goo glegroups.com:
          >
          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).
          >
          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 "preconditi ons" 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

          Comment

          Working...