33

Qt ユニット テスト (サブ) プロジェクトがあり、1 つのクラスが生成されます (メインは によって生成されQTEST_APPLESS_MAINます)。コンソール アプリとして Qt Creator 内からこれを開始できます。

Q: この特定のプロジェクトにテスト ケースとして追加のクラスを追加するにはどうすればよいですか。

  1. これらのクラスに「テスト」スロット ( private Q_SLOTS) しかない場合、メソッドは呼び出されず、QTEST_APPLESS_MAIN
  2. は 1 つしか存在できないため、プロジェクト内の複数のクラスでmain(..)使用することはできません(正しいですか?)QTEST_APPLESS_MAIN
  3. もちろん、(追加の) クラスのスロットを を含む 1 つのクラスに手動で「配線」することもできますがmain、これは非常に面倒です。

では、単体テスト プロジェクトで複数のクラスに対して単体テストを実行する最良の方法は何でしょうか?

PS:「プロジェクトでの QT 単体テストの使用 - main(...) 関数の競合」では、ブログが言及されていますが、ソリューションを説明する zip をダウンロードできません。

Qt 単体テスト サブプロジェクト

4

6 に答える 6

25

リンク先のソリューションによると、単一の Qt 単体テスト プロジェクト内で 2 つ (またはそれ以上) のクラスをテストする方法は、テストする各クラスに対応するテスト クラスがあり、そのカスタムint mainを作成したことを確認することです。各テストクラスを実行します。

例えば:

class TestClassA : public QObject
{
   Q_OBJECT
public:
   TestClassA();

   ...

private Q_SLOTS:
   void testCase1();
   ...
};

class TestClassB : public QObject
{
   Q_OBJECT
public:
   TestClassB();

   ...

private Q_SLOTS:
   void testCase2();
   ...
};

void TestClassA::testCase1()
{
   // Define test here.
}

void TestClassB::testCase2()
{
   // Define test here.
}

// Additional tests defined here.

// Note: This is equivalent to QTEST_APPLESS_MAIN for multiple test classes.
int main(int argc, char** argv)
{
   int status = 0;
   {
      TestClassA tc;
      status |= QTest::qExec(&tc, argc, argv);
   }
   {
      TestClassB tc;
      status |= QTest::qExec(&tc, argc, argv);
   }
   return status;
}

明らかに、さまざまなテスト クラスを複数の翻訳単位に分散し、int main. .moc適切なファイルを含めることを忘れないでください。

于 2012-08-31T00:40:04.913 に答える
9

この同じ答えを探して、http://qtcreator.blogspot.de/2009/10/running-multiple-unit-tests.htmlから非常に良い解決策を見つけました。彼は、(DECLARE_TEST マクロを介して) 作成されたすべてのテストを登録するコンテナーを含む名前空間を作成し、それを使用してリストのすべてのテストを実行します。コードに合わせて書き直して、ここにバージョンを投稿します (私の Qt Creator バージョン: 4.1.0):

/* BASED ON
 * http://qtcreator.blogspot.de/2009/10/running-multiple-unit-tests.html
 */    
#ifndef TESTCOLLECTOR_H
#define TESTCOLLECTOR_H

#include <QtTest>
#include <memory>
#include <map>
#include <string>

namespace TestCollector{
typedef std::map<std::string, std::shared_ptr<QObject> > TestList;
inline TestList& GetTestList()
{
   static TestList list;
   return list;
}

inline int RunAllTests(int argc, char **argv) {
    int result = 0;
    for (const auto&i:GetTestList()) {
        result += QTest::qExec(i.second.get(), argc, argv);
    }
    return result;
}

template <class T>
class UnitTestClass {
public:
    UnitTestClass(const std::string& pTestName) {
        auto& testList = TestCollector::GetTestList();
        if (0==testList.count(pTestName)) {
            testList.insert(std::make_pair(pTestName, std::make_shared<T>()));
        }
    }
};
}

#define ADD_TEST(className) static TestCollector::UnitTestClass<className> \
    test(#className);

#endif // TESTCOLLECTOR_H

次に、次のようにテスト ヘッダーに ADD_TEST(class) 行を追加します。

#ifndef TESTRANDOMENGINES_H
#define TESTRANDOMENGINES_H

#include <QtTest>
#include "TestCollector.h"

class TestRandomEngines : public QObject
{
    Q_OBJECT

private Q_SLOTS:
    void test1();
};

ADD_TEST(TestRandomEngines)

#endif // TESTRANDOMENGINES_H

そして、すべてのテストを実行するには、次のようにします。

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

int main(int argc, char *argv[]) {
    auto nFailedTests = TestCollector::RunAllTests(argc, argv);
    std::cout << "Total number of failed tests: "
              << nFailedTests << std::endl;
    return nFailedTests;
}
于 2016-12-29T18:44:27.023 に答える