11

I'm stating in QT C++ world. I'm doing TDD using QTest class. I want to verify that in certain conditions an exception is thrown by my class under test. Using google test, I would use something like:

EXPECT_THROW(A(NULL), nullPointerException);

Does it exists something like this feature in QTest? O at least a way to do it?

Thanks!

Killrazor
  • 6,856
  • 15
  • 53
  • 69
  • 1
    exceptions are not very common in the qt world. There is afaik no specific macro in QTest for this, but you could make a try catch block an test it with QVERIFY. Alternatively you could also use google test with qt (which is, for several reasons, much better than qtest imho) – TWE Feb 20 '13 at 12:32
  • Yes, by this time I'm realizing that gtest is far better than QTest. Thanks! – Killrazor Feb 20 '13 at 12:37
  • moreover, gtest supports gmock while there is nothing like this for QTest. QTest is really just for casual use, not for good UT. The only thing you need from QTest, if you use gtest, is QSignalSpy. All other things are much better in gtest. – ixSci Feb 20 '13 at 14:36
  • The second answer should be the correct one now! – Mr. Developerdude Mar 18 '17 at 17:53

2 Answers2

15

Since Qt5.3 QTest provides a macro QVERIFY_EXCEPTION_THROWN that provides the missing feature.

RA.
  • 7,542
  • 1
  • 34
  • 35
Silicomancer
  • 8,604
  • 10
  • 63
  • 130
  • The only problem with this is that `If not-substitutable type of exception is thrown or the expression doesn't throw an exception at all, then a failure will be recorded in the test log and the test won't be executed further.`. Which means that there is practically no out-of-the-box solution which allows you to check if something **doesn't throw** the given exception type (or derived one). – rbaleksandar Nov 03 '16 at 09:05
  • How would one verify that the standard constructor is deleted? Testing it with the macro is throwing an exception and aborting execution. – Matthias Herrmann Apr 08 '18 at 13:43
7

This macro demonstrates the principle.

The typeid comparison is a special use case, so may or may not want to use it - it allows the macro to 'fail' the test even when the thrown exception is derived from the one you are testing against. Often you won't want this, but I threw it in anyway!

#define EXPECT_THROW( func, exceptionClass ) \
{ \
    bool caught = false; \
    try { \
        (func); \
    } catch ( exceptionClass& e ) { \
        if ( typeid( e ) == typeid( exceptionClass ) ) { \
            cout << "Caught" << endl; \
        } else { \
            cout << "Derived exception caught" << endl; \
        } \
        caught = true; \
    } catch ( ... ) {} \
    if ( !caught ) { cout << "Nothing thrown" << endl; } \
};

void throwBad()
{
    throw std::bad_exception();
}

void throwNothing()
{
}

int main() {
    EXPECT_THROW( throwBad(), std::bad_exception )
    EXPECT_THROW( throwBad(), std::exception )
    EXPECT_THROW( throwNothing(), std::exception )

    return EXIT_SUCCESS;
}

Returns:

Caught
Derived exception caught
Nothing thrown

To adapt it for QTest you will need to force a fail with QFAIL.

cmannett85
  • 21,725
  • 8
  • 76
  • 119
  • Why don't you use `catch (const exceptionClass& e ) { \ if ( typeid( e ) == typeid( exceptionClass ) ) {` to be independent from std::exception? – ixSci Feb 20 '13 at 14:38
  • Because if the exception is not or does not derive from `exceptionClass` the `catch` block would be skipped. – cmannett85 Feb 20 '13 at 14:42
  • 1
    I see, then it is enough to add catch(...) and count it as an unhandled – ixSci Feb 20 '13 at 14:43
  • Yes your right, so if it is not std::exception or derived it would not cause the QTest app to abort. – cmannett85 Feb 20 '13 at 14:46
  • 1
    I meant a little bit different, not just add `catch(...)` but also replace `catch ( std::exception& e )` with `catch (const exceptionClass& e )` then it will be a full solution. – ixSci Feb 20 '13 at 14:48
  • Its perfect for me. The only gotcha is that QT always returns an unhandledException when exception isn't derived from QException. Maybe is better to return to the old return code mode – Killrazor Feb 20 '13 at 22:53