2010-04-30 2 views
2

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

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

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

...

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

Так вот мой main.cpp файл:

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

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

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

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

My Fatal: УТВЕРЖДАЕТ неудачу в MyClass :: DoSomething: "DoSomething()", файл myclass.cpp, line 21 Программа неожиданно закончила.

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

ответ

1

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

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

Я не смог найти браузер для текущего исходного кода в Интернете, но the Qt-4.2.2 source code is mostly identical и должен дать вам общее представление о том, что происходит.

+0

Qt с открытым исходным кодом, здесь все в порядке: http://qt.gitorious.org/qt –

+0

Спасибо, Калеб. Разит. Вид драконов, но я думаю, что я просто использую препроцессор, чтобы исключить тесты «ожидаемого отказа» из отладочных сборников и тестировать их только на сборках релизов. –

+0

Спасибо @Adam - я проверил github, но не смог найти его там, и Google не перечислил его в любом месте в результатах поиска. –

3

Q_ASSERT_X ничего не скомпилирует при создании выпуска.

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

+0

Наши посты пересекли; это был именно мой вывод. (См. Комментарий на ответ Калеба.) Великие умы действительно думают одинаково .... :) –

0

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

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

Тогда вы могли бы иметь некоторые собственные утверждать, макрос:

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

И использовать его в коде, как:

CUSTOM_QEXPECT_FAIL(testedObj->panicAtTheDisco()); 

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

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

Смежные вопросы