2010-04-30 139 views
2

我的Qt應用程序使用Q_ASSERT_X,它調用qFatal(),它默認會中止應用程序。這對於應用程序來說很好,但是我想在單元測試應用程序時抑制這種行爲。 (我使用的是Google Test Framework。)我在單獨的項目中使用單元測試,靜態鏈接到正在測試的類。該documentation爲qFatal()讀取:如何防止qFatal()中止應用程序?

調用與 致命的消息MSG的消息處理程序。如果未安裝消息 處理程序,則 消息將打印到stderr。在Windows的 下,該消息被髮送到 調試器。

如果您使用默認消息 處理函數,此函數將在 Unix系統上中止以創建核心轉儲。在 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(); 
} 

但我的應用程序是在斷言仍停止。我可以告訴大家,我的自定義處理程序被調用,因爲我運行測試時的輸出是:

我的致命:ASSERT失敗 MyClass的:: DoSomething的:「DoSomething的()」, 文件myclass.cpp,第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 – 2010-04-30 19:54:29

+0

謝謝,Kaleb。臭死了。那種嚴厲的,但我想我只是使用預處理器從調試版本中排除「預期的失敗」測試,並且只針對發佈版本進行測試。 – 2010-04-30 19:57:07

+0

感謝@亞當 - 我檢查了github,但在那裏找不到它,Google沒有在搜索結果中的任何合理位置列出它。 – 2010-04-30 20:13:59

3

Q_ASSERT_X在進行發佈構建時編譯爲無。

因此,對於單元測試,做一個發佈版本,它不會調用qFatal。

+0

我們的帖子越過;這正是我的結論。 (查看關於Kaleb的答案的評論。)偉大的思想家們確實相似...... :) – 2010-04-30 19:58:50

2

-DqFatal = qCritical :)

0

在某些情況下,你可能無法surpress 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()); 

並不是說這是一種很好的方法,只是試圖證明可以解決問題。

此外,我沒有仔細閱讀,你是靜態鏈接測試類。在這種情況下,存根不可能工作,只有在您將其構建到您的測試可執行文件時。