Pretty-Printing Output for QCOMPARE

We have created a custom class, say Person, and use it in a unit test.

void TestPerson::testEquality()
    Person p1("Alice", 42);
    Person p2("Bob", 37);
    QCOMPARE(p1, p2);

The unit test fails with this message.

FAIL!  : TestPerson::testEquality() Compared values are not the same
   Loc: [../QComparePrint/TestPerson.cpp(8)]

This message does not tell us how the two Person objects differ. We would like to see this message as we would see it for any type known to QCOMPARE.

FAIL!  : TestPerson::testEquality() Compared values are not the same
   Actual   (p1): "Person(Alice, 42)"
   Expected (p2): "Person(Bob, 37)"
   Loc: [../QComparePrint/TestPerson.cpp(16)]

How do we achieve such a pretty-printed output for QCOMPARE?

The solution turns out to be very simple. The QCOMPARE documentation gives the crucial hint.

For your own classes, you can use QTest::toString() to format values for outputting into the test log.

Unfortunately, the documentation links to the first overload of QTest::toString(), which is irrelevant for our problem. If we don’t give up and scroll down to the last overload of QTest::toString(), we will be rewarded. It suggests to overload toString() in the namespace of our class Person. Using the example from the documentation, we can quickly come up with our own overload of toString().

char *toString(const Person &p)
    return QTest::toString("Person(" + p.firstName() + ", " +
                           QString::number(p.age()) + ")");

Our overload assembles a formatted string of a Person object and passes this string to QTest::toString(const QString &value).

If we use QCOMPARE on Person objects only in one test class, we add our new toString() function to the source file of this test class. If we use it in several test classes, we put the function in a custom test library containing common test functionality.

You can find the example code on github.

Leave a Reply

Your email address will not be published. Required fields are marked *