3

私の Qt アプリケーションは、(デフォルトで) アプリケーションを中止する qFatal() を呼び出す Q_ASSERT_X を使用します。これはアプリケーションにとっては素晴らしいことですが、アプリケーションの単体テスト時にはその動作を抑制したいと考えています。(私はGoogle Test Frameworkを使用しています。)別のプロジェクトで単体テストを行い、テストしているクラスに静的にリンクしています。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();
}

しかし、私のアプリケーションはまだアサートで停止しています。テストを実行したときの出力は次のとおりであるため、カスタム ハンドラーが呼び出されていることがわかります。

My Fatal: 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.cppvoid qt_message_output(QtMsgType msgType, const char *buf)ハンドラがインストールされているかどうかを最初にチェックするものを定義します。そうであればそれを呼び出し、それ以外の場合はデフォルトのハンドラーを使用します。その直後に、ほとんどの場合、中止 (Unix/MingWn) するか、exit を呼び出します (その他)。

オンラインで現在のソース コードのブラウザを見つけることができませんでしたが、Qt-4.2.2 のソース コードはほとんど同じで、何が起こっているのかを大まかに把握できるはずです。

于 2010-04-30T19:15:16.740 に答える
0

場合によっては、qFatal を抑制して黙って続行することができない場合があります。テストされたコンポーネントは、とにかく数行後にクラッシュが発生するような状態になる可能性があります。それを回避する1つの方法は、テストコードのどこかに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() );

これが良い方法だと言っているのではなく、問題に対して何かできることを証明しようとしているだけです。

さらに、テスト済みのクラスに対して静的にリンクしていることを十分に注意深く読んでいませんでした。その場合、スタブはおそらく機能しません。テスト実行可能ファイルにビルドする場合のみです。

于 2010-06-02T22:20:40.450 に答える