Menu

Using auxiliary methods

Help
2005-08-11
2013-04-22
  • Jakub Brzezniak

    Jakub Brzezniak - 2005-08-11

    Hello

    Let's assume I have a class called A with four members: a, b, c and d. During the testing, whenever I would want to check if the values of all the members are correct, I would have to make four assertions. It would be much simpler to create a method like this:

    void compareA (const A& o, int a, int b, int c, int d)
    {
        CPPUNIT_ASSERT (o.a == a)
        CPPUNIT_ASSERT (o.b == b)
        /* ... */
    }

    and call it everytime I would like to check the members. But there is one problem with that: if an assertion fails, then I will get the line number inside the compareA() method, and not the line number the method was called at. In my own basic unit testing classes I have solved it by creating a macro CALL, used in the following way:

    CALL (compareA (a, 0, 0, 0, 0))

    The macro simply adds the method name and location to the current test path (and removes them after calling the method), and so, on failure I get the whole path leading to the assertion:

    MyTest
    compareA file.cpp 50
    file.cpp 10

    Of course, this could be used in a nested way (if compareA() would call another method this way), and the information about a failure could look like this:

    MyTest
    compareA file.cpp 50
    anotherMethod file.cpp 52
    file.cpp 10

    Is there a way to do something like this in CPPUNIT? As I have seen so far, only the location of the assertion that failed is stored and I haven't found any macro or method for doing this in the documentation.

    I know that for this example I could create a simple macro instead of the compareA method, but I would like to use this feature for much more complex auxiliary methods, and it would be much more convenient to use methods and not macros.

    Regards,
    Jakub

     
    • Tom Plunket

      Tom Plunket - 2005-08-11

      Don't do that.  :)

      If you want to compare two of these things for equality, define an operator== that takes two of them, and have it return true or false, based on whether or not all of the elements match.  Then, just use CPP_UNIT_ASSERT_EQUAL(a, b) and be done.

      Oh, that means that you unit-test the development of this operator== to make sure that it works properly.  ;)  It also means that you'll probably need to write a bit of code to format the output of your object (e.g. operator<<(ostream&, your_object&) needs to be defined), but it'll be worth doing it after only two uses of it.  ;)

      In general, try to limit yourself to one assertion per test case.  I can't effectively explain why here, but I've found it's really a good way to go, and someone smarter than me wrote a book and said so, too.  ;)

       
    • Jakub Brzezniak

      Jakub Brzezniak - 2005-08-11

      Yeah, I could do this :). I haven't thought about it when I was writing the example, and I admit it's pretty dumb :P.

      However, I use these auxiliary methods in tests which cannot be changed that easily (or at least I think so ;)) and it would be really nice if there was a way to trace such calls. Is it possible?

      Regards,
      Jakub

       
      • Code Guru

        Code Guru - 2005-08-11

        I'm not sure how to get the stacktrace, as it is called, to appear in the output for your test suite.  However, if you run it in a debugger, such as gdb, you can easily display the complete history of method calls.

         
        • Jakub Brzezniak

          Jakub Brzezniak - 2005-08-12

          Well, this would rather be an uncomfortable solution because I would have to debug every time a test using an auxiliary method failed. It would be much easier if it was handled by CppUnit and I could get the information about the auxiliary method calls in the output.

           
          • Code Guru

            Code Guru - 2005-08-13

            Granted, but it is the only suggestion I can think of as I am new to CppUnit myself.  I apologize that I cannot provide any further help.

            Layne

             
            • Jakub Brzezniak

              Jakub Brzezniak - 2005-08-13

              No problem. Thank you for your help anyway :).

               
      • Tom Plunket

        Tom Plunket - 2005-08-13

        If you can't change the auxilliary functions, you're out of luck.  If you can, just follow my earlier advice and keep the assertions in the test methods themselves.  It will be so much cleaner, clearer, and simpler.

        Ok, technically speaking you could inject some code into CppUnit as, say, "m_overloadFilename" and "m_overloadLineNumber," but then you'd have to put tons of calls to the thing that set those up throughout your testing code.  I.e., you'd still have to edit the testing code itself.  However, this again makes your tests more complicated and more fragile, and the point of unit testing is that the tests are dead-simple.

        Things that can't easily be changed won't be until you make the effort to do so.  However, there's no reason to remove "legacy" things that work.  Just add the functionality I discussed and use it for new code.  If the old tests ever require revisiting (even if only because they start failing), then those can be upgraded to suit.

        Just remember: one assertion per test case makes your life a LOT easier.

         
        • Jakub Brzezniak

          Jakub Brzezniak - 2005-08-13

          I think that at least for now the best solustion will be if I store the names and locations of the auxiliary method calls in a global array and create my own assertion macros that will convert the array to a string and then call the CPPUNIT_xxxx_MESSAGE macro with the string passed as the message. It won't be the best solution (it won't allow to go to the location of the auxiliary method call with a click for example) but it should be enough for now.

          However, I have also posted a request for this feature to the Open Discussion forum. Maybe other CppUnit users will find it useful too.

          Thank you for your help.

           

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.