Use QTest macros (QVERIFY, QCOMPARE, etc.) in function other than the test function

825 views Asked by At

In general, the macros QVERIFY, QCOMPARE, etc. shall not be used outside a test function. The reason is, that in case of a failure, they interrupt the test with a return.

If I want to do tests in a function, I should do them by hand and return false if one of them fails. Then call the function with QVERIFY. But when I do this, I miss out the detailed output of the macros like the line where the error occurred.

So I'm looking for a way to use the macros outside of a test function. One solution is to create my own macro that interrupts the test when a macro call in the underlying function fails. The main problem here is to detect when a test has failed. Looking into Qt's code, in case of a fail the variable QTest::failed is set to true. But I don't have access to this variable.

Is there a way to find out if a QtTest macro has failed?

1

There are 1 answers

0
IceFire On

Yeah, Qt does not really offer anything here because the test will not really get interrupted within your own function. The control flow cannot be as easily disturbed. You would need to throw an exception and make sure it's correctly caught.

What I'm doing now is just returning a const char* (works when using a string literal). If the function actually returns something, std::variant can be used, e.g.:

std::variant<MyObject, const char*> createObject() {
    // do some preparations
    if(preparationsFail) {
        return "Error occurred";
    
    // all worked

    // ...: create some myObject 
    return myObject;
}

void MyTest::testFunction() {
    auto result = createObject();
    if(const char** error = std::get_if<const char*>(&result)) {
        QVERIFY2(false, *error); // we get pointer to value, so type is **
    }
    
    // else, work with myObject by std::get<MyObject>(result);
}

Not as concise as would be desired, but it works.

It can be made more beautiful by wrapping const char* and, depending on your style, by using std::visit etc. but that's up to you and your style.