Как предотвратить прерывание приложения qFatal ()?


Мое приложение Qt использует Q_ASSERT_X, который вызывает qFatal (), который (по умолчанию) прерывает приложение. Это здорово для приложения, но я хотел бы подавить это поведение при модульном тестировании приложения. (Я использую Google Test Framework .) У меня есть модульные тесты в отдельном проекте, статически связанные с классом, который я тестирую. Документация для qFatal () гласит:

Вызывает обработчик сообщений с помощью роковое сообщение сообщение. Если нет сообщения обработчик был установлен, сообщение печатается в stderr. Под Windows, сообщение отправляется в отладчик.

Если вы используете сообщение по умолчанию обработчик эта функция будет прервана на Системы Unix для создания дампа ядра. На Windows, для отладочных сборок, это функция сообщит о _CRT_ERROR возможность подключения отладчика к приложение.

...

Для подавления вывода во время выполнения, установите свой собственный обработчик сообщений с помощью qInstallMsgHandler ().

Итак, вот мой главный.cpp файл:

#include <gtest/gtest.h>
#include <QApplication>

void testMessageOutput(QtMsgType type, const char *msg) {
    switch (type) {
    case QtDebugMsg:
        fprintf(stderr, "Debug: %sn", msg);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %sn", msg);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %sn", msg);
        break;
    case QtFatalMsg:
        fprintf(stderr, "My Fatal: %sn", msg);
        break;
    }
}

int main(int argc, char **argv)
{
    qInstallMsgHandler(testMessageOutput);
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Но мое приложение все еще останавливается на assert. Я могу сказать, что вызывается мой пользовательский обработчик, потому что вывод при запуске моих тестов:

Мой фатальный: утверждение неудачи в MyClass:: doSomething: "doSomething()", файл myclass.cpp, строка 21 программа неожиданно закончил.

Что я могу сделать, чтобы мои тесты продолжали работать даже тогда, когда assert терпит неудачу?

4 2

4 ответа:

По крайней мере, для Qt-4.6.2 вы ничего не можете сделать.

src/corelib/global/qglobal.cpp определяет void qt_message_output(QtMsgType msgType, const char *buf) , который сначала проверяет, установлен ли обработчик a. Если это так, то он вызывает его, в противном случае он использует обработчики по умолчанию. Сразу после этого он почти всегда прерывается (Unix/MingWn) или вызывает exit (others).

Я не смог найти браузер для текущего исходного кода в интернете, ноисходный код Qt-4.2.2 в основном идентичен и должен дать вам общее представление о том, что происходит.

Q_ASSERT_X компилируется в ничто при выполнении сборки выпуска.

Итак, для модульного тестирования выполните сборку выпуска, и она не вызовет qFatal.

- DqFatal=qCritical:)

В некоторых случаях вы, возможно, не сможете преодолеть qFatal и продолжить молча, тестируемый компонент может быть в таком состоянии, что сбой произойдет в любом случае после нескольких строк. Один из способов избежать этого может быть заглушить qFatal где-то в вашем тестовом коде ;)

void qFatal(const char *msg, ...)
{
    QT_THROW(std::some_exception);
}

Тогда у вас может быть собственный макрос assert:

#define CUSTOM_QEXPECT_FAIL( method ) { bool failed = false;\
    try { \
        method ; \
    }\
    catch(...) { \
        failed = true; \
    } \
    QVERIFY(failed); }

И используйте его в своем коде, например:

CUSTOM_QEXPECT_FAIL( testedObj->panicAtTheDisco() );

Не говорю, что это в любом случае хороший подход, просто пытаюсь доказать, что что-то можно сделать для вопрос.

Кроме того, я недостаточно внимательно прочитал, что вы статически связываетесь с тестируемым классом. Stubbing, вероятно, не работает в этом случае, только если вы встроите его в свой тестовый исполняемый файл.