12

Qtのユニットテストシステムでいくつかのテストを書き始めました。

通常、どのようにテストを整理しますか?1つのモジュールクラスごとに1つのテストクラスですか、それとも1つのテストクラスでモジュール全体をテストしますか?Qtドキュメントは、前者の戦略に従うことを提案しています。

モジュールのテストを書きたい。このモジュールは、モジュールユーザーが使用するクラスを1つだけ提供しますが、他のクラスには多くのロジックが抽象化されており、パブリッククラスのテスト以外にもテストしたいと思います。

問題は、Qtが提案したテストの実行方法にQTEST_MAINマクロが含まれていることです。

QTEST_MAIN(TestClass)
#include "test_class.moc"

そして最終的には、1つのテストプログラムで1つのテストクラスだけをテストできます。そして、モジュール内のすべてのクラスのテストプロジェクトを作成するのはちょっと面倒です。

もちろん、QTEST_MAINマクロを見て、それを書き直して、他のテストクラスを実行することもできます。しかし、箱から出してすぐに機能する何かがありますか?

これまでのところ、私は手作業でそれを行っています:

#include "one.h"
#include "two.h"

int main(int argc, char *argv[]) 
{ 
    QCoreApplication app(argc, argv); 
    TestOne one;
    QTest::qExec(&one, argc, argv);
    TestOne two;
    QTest::qExec(&two, argc, argv);
}
4

4 に答える 4

6

@cjhuittによって投稿された回答に関連する

これは、各テストオブジェクトを手動で呼び出す必要がない例です。

私はこのようなことを避けようとします:

MyTestClass1 t1;   t1.run();
MyTestClass2 t2;   t2.run();
//etc...

私の解決策は、静的リストに自分自身を追加する基本クラスからテストオブジェクトを継承させることです 。メインプログラムは、そのリスト内のすべてのテストオブジェクトを実行します。このようにして、サポートするフレームワークコードを変更する必要はありません。変更されるのは、テストクラス自体だけです。

これが私がそれをする方法です:

qtestsuite.h-テストオブジェクトの基本クラス

#ifndef QTESTSUITE_H
#define QTESTSUITE_H

#include <QObject>
#include <vector>

class QTestSuite : public QObject
{
    Q_OBJECT
public:
    static std::vector<QObject*> m_suites;

public:
    explicit QTestSuite();

};

#endif // QTESTSUITE_H

qtestsuite.cpp

#include "qtestsuite.h"
#include <iostream>

std::vector<QObject*> QTestSuite::m_suites;

QTestSuite::QTestSuite() : QObject()
{
    m_suites.push_back(this);
}

testall.cpp-テストを実行します

#include "qtestsuite.h"

#include <QtTest/QtTest>
#include <iostream>

int main(int, char**)
{
    int failedSuitesCount = 0;
    std::vector<QObject*>::iterator iSuite;
    for (iSuite = QTestSuite::m_suites.begin(); iSuite != QTestSuite::m_suites.end(); iSuite++)
    {
        int result = QTest::qExec(*iSuite);
        if (result != 0)
        {
            failedSuitesCount++;
        }
    }
    return failedSuitesCount;
}

mytestsuite1.cpp-サンプルテストオブジェクト、これらをさらに作成します

#include "qtestsuite.h"

#include <QtTest/QtTest>

class MyTestSuite1: public QTestSuite
{
     Q_OBJECT
private slots:
    void aTestFunction();
    void anotherTestFunction();
};

void MyTestSuite1::aTestFunction()
{
    QString str = "Hello";
    QVERIFY(str.toUpper() == "this will fail");
}

void MyTestSuite1::anotherTestFunction()
{
    QString str = "Goodbye";
    QVERIFY(str.toUpper() == "GOODBYE");
}

static MyTestSuite1 instance;  //This is where this particular test is instantiated, and thus added to the static list of test suites

#include "mytestsuite1.moc"

また、.proファイルを作成するには

qmake -project "CONFIG += qtestlib"
于 2014-06-29T13:44:35.823 に答える
5

QTestを使用したセットアップでは、より良いものにするためにいくつかのことを行いました。

  • 新しい単体テストクラスの基本クラスとして使用されるQObjectのサブクラスを定義します。
  • そのクラスのコンストラクターで、テストのインスタンスをテストの静的リストに追加し、デストラクタでそれを削除します。
  • 次に、テストをループし、を使用してテストを実行する静的関数がありますQTest::qExec()。(毎回返される値を累積し、関数から返します。)
  • main()この関数を呼び出し、結果を成功/失敗として返します。
  • 最後に、特定のテスト自体のコンパイルユニットには、通常、そのクラスの静的インスタンスが含まれています。

この設定は、main()実行前にクラスがインスタンス化されることを意味するため、メインの実行時にテストするクラスのリストに追加されます。フレームワークでは、クラスを適切に継承し、常に実行する場合は静的インスタンスをインスタンス化する必要があります。

また、コマンドラインスイッチに基づいて追加される他のオプションのテストを作成することもあります。

于 2010-05-03T18:15:23.073 に答える
4

ええ、QTestは少し奇妙なテスト構造を強制し、一般的にGoogle Test /MockFrameworkより劣っています。1つのプロジェクトでは、QTest(クライアント要件)を使用する必要があります。使用方法は次のとおりです。

  1. すべてのテストをサブディレクトリテンプレートプロジェクトとしてまとめてコンパイルします
  2. 新しいテストの作成を簡単にするために、すべてのtest .proファイルに含めるcommon.priファイルを使用して、多くのプロジェクト構成を共有しています。
  3. 可能であれば、オブジェクトファイルディレクトリを共有してコンパイルを高速化します
  4. 私はそれらすべてをbatch+awk+sedスクリプトを使用して実行します。

この4つのポイントの設定は非常に簡単で、QTestの使用がほぼ快適になります。上記の設定では解決されない複数のテストの実行に問題がありますか?

PS:テストを同じ方法で実行します。つまり、複数のQTest :: qExecを呼び出すと、-oコマンドラインスイッチで問題が発生します。最後にテストしたクラスの結果のみが表示されます。

于 2010-05-02T18:50:28.210 に答える
0

通常、テスト対象のクラスごとに1つのテスト実行可能ファイルを使用してテストを編成します。

そして最終的には、1つのテストプログラムで1つのテストクラスだけをテストできます。

これは良いことです。テストを相互に分離し、1つのテストでのクラッシュなどが他のすべてのテストをブロックするのを防ぎます。このクラッシュは、テスト中のいくつかのクラスの共通コンポーネントが原因である可能性があります。失敗のパターンは、問題の根本的な原因にあなたを導きます。基本的に、テストが互いに独立している場合は、障害の診断情報が向上します。

複数の実行可能ファイルを簡単に設定し、各テストを個別に実行できるようにします。テストランナーを使用して、すべてのテストプロセスを生成します。

アップデート:

私はこれについて少し考えを変えました。たくさんのテストを含む大きなプログラムを作成すると、何百ものテスト実行可能ファイルのリンクが非常に遅くなります。私の新しい設定は、ライブラリのすべてのテストを実行可能ファイルに入れ、テスト実行可能ファイルに渡されるコマンドライン引数を使用して呼び出すテストを選択することです。

これにより、実行可能ファイルの数が数百から数十に削減されますが、テストを個別に実行する利点は維持されます。

于 2011-03-04T22:32:49.010 に答える