Как предотвратить прерывание приложения 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 ответа:
По крайней мере, для 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.
В некоторых случаях вы, возможно, не сможете преодолеть 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, вероятно, не работает в этом случае, только если вы встроите его в свой тестовый исполняемый файл.