3

我的 Qt 应用程序使用 Q_ASSERT_X,它调用 qFatal(),它(默认情况下)中止应用程序。这对应用程序来说很好,但我想在对应用程序进行单元测试时抑制这种行为。(我正在使用Google 测试框架。)我在一个单独的项目中进行单元测试,静态链接到我正在测试的类。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();
}

但是我的应用程序仍然在断言处停止。我可以说我的自定义处理程序正在被调用,因为运行我的测试时的输出是:

我的致命:MyClass::doSomething 中的 ASSERT 失败:“doSomething()”,文件 myclass.cpp,第 21 行 程序意外完成。

即使断言失败,我该怎么做才能让我的测试继续运行?

4

4 回答 4

5

Q_ASSERT_X在进行发布构建时编译为空。

所以,对于单元测试,做一个发布版本,它不会调用 qFatal。

于 2010-04-30T19:56:27.203 回答
2

-DqFatal=qCritical :)

于 2010-04-30T21:59:02.757 回答
1

至少对于 Qt-4.6.2,你无能为力。

src/corelib/global/qglobal.cpp定义void qt_message_output(QtMsgType msgType, const char *buf)首先检查是否已安装处理程序。如果是这样,它会调用它,否则它使用默认处理程序。紧接着,它几乎总是中止(Unix/MingWn)或调用 exit(其他)。

我在网上找不到当前源代码的浏览器,但Qt-4.2.2 源代码大部分是相同的,应该让您大致了解正在发生的事情。

于 2010-04-30T19:15:16.740 回答
0

在某些情况下,您可能无法抑制 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() );

并不是说这在任何方面都是好方法,只是试图证明可以为这个问题做点什么。

另外,我没有仔细阅读,您正在静态链接测试类。存根在这种情况下可能不起作用,除非您将其构建到您的测试可执行文件中。

于 2010-06-02T22:20:40.450 回答