Tracing auxiliary method calls

  • Sometimes during writing a test, it would be a good idea to write an auxiliary method. For example, if an object can have ten states, and ten methods of the object return values strictly dependent on its state, we could create a method:

    testState (state, value1, value2, ...)
        Object o;
        o.setState (state);
        CPPUNIT_ASSERT (o.getValue1() == value1);
        CPPUNIT_ASSERT (o.getValue2() == value2);
        /* ... */

    and then in the test do this:

    testState (state1, state1_value1, state1_value2, ...);
    testState (state2, state2_value1, state2_value2, ...);
    /* ... */

    This can really save a lot of writing and simplifies updating the tests - instead of 100 lines, the tests will be done in 10 lines, and if a new state appears, then testing the methods for that new state will be a matter of adding only one line to the test (sometimes this could be also achieved by using two-dimensional arrays of expected values, but sometimes using arrays instead of auxiliary methods is not possible or very hard). If the tests performed by testState() were more complex than the ones in this example, then testState() could even call another auxiliary method (this is a rather rare case, because it can complicate the tests too much, but sometimes it simplifies the tests - it all depends on the particular case).

    However, this would require a possibility of tracing the calls to the auxiliary methods, which unfortunately CppUnit doesn't seem to have (I haven't found anything about such possibility in the documentation). This doesn't make such methods very useful, because in case of a failure, you would only get the location of the assertion within the auxiliary method that failed, without any information regarding the method call (or calls) that led to the failure.

    I would really like to see this feature in CppUnit because it has proven very useful in my own basic testing classes. It is very easy to implement, and below I put an example of how it could be done:

    The auxiliary methods could be called using a CPPUNIT_CALL macro, like this:

    CPPUNIT_CALL (auxiliaryMethod (arg1, arg2, ...))

    defined in the following way:

    #define CPPUNIT_CALL(method)\     m_calls.push (CallInfo (#method, __FILE__, __LINE__));\     method;\     m_calls.pop ();

    The CallInfo class would store the information about one call of the auxiliary method (its location and the method call as a string). The m_calls would be a member of the Test class and would be defined as an array of CallInfo (it should be an array to allow calling one auxiliary method from another one, in case of such need).

    The Asserter methods, in case of a failure, would get the array from the Test that failed (or they could accept it as an additional argument) and would store its copy in the TestFailure object. The information about the auxiliary method calls leading to the failure could then be easily printed out. And that's all :).

    Of course this was only an example and it could be done in any other way.

    Does anyone else think that it would be a useful feature? If yes, then I would really like to know if I can hope that it will be implemented in future versions of CppUnit.