どのユニット-テスティングフレームワークを使用すれば良いのQt?[定休日]

StackOverflow https://stackoverflow.com/questions/1524390

質問

私は始めの新しいプロジェクトにもクロスプラットフォームGUIとして選ばれたQtのGUI-枠組み

必要としていますユニット-テスティングフレームワークです。までは前年同期を使わせてもらいました自社開発のユニット-テスティングフレームワークのためのC++プロジェクトを移行します試験のための新規プロジェクト.

いい経験用試験のためのQt-。はQtTest/QTestLibィ?

まだまだだとどのくらい使用したいQtの非GUIのプロジェクト-しろうりん、STL/ブーストをコアコードの小さなインターフェースのQt-ベす。

編集: というのが多い傾向QtTest.がいをお持ちの方ならどなたでも経験を統合するねじ一杯まで入れ、ネジ部の山に統合サーバー?また、こうと思っていることに対応のアプリケーションのための新しいテストケースが多くの摩擦を実現しています。あるのに良い方法で解決す。はQt Creatorしての取り扱いなどのテストケースや必要なプロジェクト毎にテストケース?

役に立ちましたか?

解決

私はQTestLibは、このような一般的な用語で、他に1つのフレームワークよりも「より良い」であることを知りません。そこにはよくない一つのことはあり、それはQtのベースのアプリケーションをテストする良い方法を提供します。

あなたは、新しいGoogleのテストベースのセットアップにQTestを統合することができます。私はそれを試してみましたが、QTestLibが設計されてどのように基づいていない、あまりにも複雑ではありませんように思えるます。

純粋QTestLibで書かれたテストは継続的インテグレーションサーバのための必要な形式に変換するためにいくつかのXSLT変換と一緒に、あなたが使用することができ-xmlオプションがあります。しかし、その多くは、あなたが一緒に行くどのCIサーバーに依存します。私は、同じことがGTESTに適用される想像ます。

テストケースごとに単一のテストアプリは私のために多くの摩擦を引き起こしたことはありませんが、それはテストケースの構築と実行を管理するのまともな仕事をするだろうビルドシステムを持つに依存します。

私は、テストケースごとに別々のプロジェクトを必要とするのQt Creatorの中に何も知りませんが、それは、私はQtの創造主を見て最後の時間以降に変更された可能性があります。

私はまたQtCoreに固執し、STLから離れて滞在をお勧めします。全体QtCoreを使用すると、簡単にQtのデータ型を必要とGUIのビットを扱うようになります。あなたは、その場合には別のデータ型からの変換を心配する必要はありません。

他のヒント

あなたは独立したテスト・アプリケーションを作成する必要はありません。

:ちょうどこの1に類似の独立したmain()関数でqExecを使用
int main(int argc, char *argv[])
{
    TestClass1 test1;
    QTest::qExec(&test1, argc, argv);

    TestClass2 test2;
    QTest::qExec(&test2, argc, argv);

    // ...

    return 0;
}

これは、1つのバッチ内の各クラス内のすべてのテストメソッドを実行します。

次のようにあなたのTestClassを.hファイルにはなります:

class TestClass1 : public QObject
{
Q_OBJECT

private slots:
    void testMethod1();
    // ...
}

残念ながら、この設定は実際に多くの人々のために非常に有用であると思われるにもかかわらず、Qtのドキュメントで十分に記述されていません。

ジョーの答えに追加するには。

ここでは、イベントループを産卵ユーティリティクラスを含む、(testrunner.h)を使用し、小さなヘッダ(これは、例えば、試験に必要とされる信号スロット接続とデータベースのキューに入れられた)および「実行中」QTest互換クラスです

#ifndef TESTRUNNER_H
#define TESTRUNNER_H

#include <QList>
#include <QTimer>
#include <QCoreApplication>
#include <QtTest>

class TestRunner: public QObject
{
    Q_OBJECT

public:
    TestRunner()
        : m_overallResult(0)
    {}

    void addTest(QObject * test) {
        test->setParent(this);
        m_tests.append(test);
    }

    bool runTests() {
        int argc =0;
        char * argv[] = {0};
        QCoreApplication app(argc, argv);
        QTimer::singleShot(0, this, SLOT(run()) );
        app.exec();

        return m_overallResult == 0;
    }
private slots:
    void run() {
        doRunTests();
        QCoreApplication::instance()->quit();
    }
private:
    void doRunTests() {
        foreach (QObject * test, m_tests) {
            m_overallResult|= QTest::qExec(test);
        }
    }

    QList<QObject *> m_tests;
    int m_overallResult;
};

#endif // TESTRUNNER_H

このようにそれを使用します:

#include "testrunner.h"
#include "..." // header for your QTest compatible class here

#include <QDebug>

int main() {
    TestRunner testRunner;
    testRunner.addTest(new ...()); //your QTest compatible class here

    qDebug() << "Overall result: " << (testRunner.runTests()?"PASS":"FAIL");

    return 0;
}

私は私のアプリのためにQtTestを使用してオフに開始し、非常に、非常に迅速にそれで限界に走り出しました。二つの主要な問題であった。

1)私のテストは非常に高速に実行する - 十分に速く、実行ファイルを読み込むなど)、必要に応じて(Q(コア)アプリケーションを設定するのオーバーヘッドは、多くの場合、テストそのものの運転時間を矮星こと!各実行可能ファイルをリンクすることも、多くの時間を占めています。

オーバーヘッドはちょうどより多くのクラスが追加されたとして増加に保たれ、そしてそれはすぐに問題になった - ユニットテストの目標の一つは、それがすべて負担ではないことをとても速く走るセーフティネットを持っています、これは、急速にそうではありませんになってきました。溶液を1つの実行可能ファイルに複数のテストスイートをグロブすることであり、(上記のように)、これは、それが主に行い、可能である一方、 をサポートし、重要な制限がありません。

2)いいえフィクスチャのサポート - 。私のための契約ブレーカを

しばらく後、私はGoogleのテストに切り替えるので - それははるかに高機能と洗練されたユニットテストフレームワーク(Googleのモックを使用する場合は特に)で、1解き)と2)、しかも、あなたはまだ簡単に使用することができますなどQSignalSpyやGUIイベントのシミュレーション、などの便利なQTestLib機能は、それは痛みのビットを切り替えることだったが、ありがたいプロジェクトはあまりにも遠く進んでいなかったとの変更の多くが自動化することができます。

個人的に、私は将来のプロジェクトのためにGoogleのテストの上にQtTestを使用されることはありません - 。私が見ることができる申し出がない本当の利点場合、および重要な欠点があります。

なぜQtの中に含まれるユニットテストフレームワークを使用していませんか? 例:

IユニットはGTESTと QSignalSpyするを使用して私たちのライブラリをテストしました。信号をキャッチするQSignalSpyを使用してください。あなたはそれらをテストするために(通常の方法のように)直接スロットを呼び出すことができます。

QtTestは、Qtのイベントループ/信号ディスパッチを必要とする部品をテストするためのほとんど有用です。それは、それがアプリケーションの残りの部分に使用し、既存のテストフレームワークと競合してはならないように、各テストケースは、別々の実行を必要とするという方法で設計されています。

(ところで、私は非常にも、アプリケーションの非GUI部品のQtCoreの使用をお勧めします。それはで動作するように非常に良くあります。)

私たちは一つでもテストクラスごとの完全なQtTestオプションをサポートし、まだバッチプラスログ内のすべてを実行することができますmlvljrさんとジョーのソリューションを拡張するには

usage: 
  help:                                        "TestSuite.exe -help"
  run all test classes (with logging):         "TestSuite.exe"
  print all test classes:                      "TestSuite.exe -classes"
  run one test class with QtTest parameters:   "TestSuite.exe testClass [options] [testfunctions[:testdata]]...

ヘッダー

#ifndef TESTRUNNER_H
#define TESTRUNNER_H

#include <QList>
#include <QTimer>
#include <QCoreApplication>
#include <QtTest>
#include <QStringBuilder>

/*
Taken from https://stackoverflow.com/questions/1524390/what-unit-testing-framework-should-i-use-for-qt
BEWARE: there are some concerns doing so, see  https://bugreports.qt.io/browse/QTBUG-23067
*/
class TestRunner : public QObject
{
   Q_OBJECT

public:
   TestRunner() : m_overallResult(0) 
   {
      QDir dir;
      if (!dir.exists(mTestLogFolder))
      {
         if (!dir.mkdir(mTestLogFolder))
            qFatal("Cannot create folder %s", mTestLogFolder);
      }
   }

   void addTest(QObject * test)
   {
      test->setParent(this);
      m_tests.append(test);
   }

   bool runTests(int argc, char * argv[]) 
   {
      QCoreApplication app(argc, argv);
      QTimer::singleShot(0, this, SLOT(run()));
      app.exec();

      return m_overallResult == 0;
   }

   private slots:
   void run() 
   {
      doRunTests();
      QCoreApplication::instance()->quit();
   }

private:
   void doRunTests() 
   {
      // BEWARE: we assume either no command line parameters or evaluate first parameter ourselves
      // usage: 
      //    help:                                        "TestSuite.exe -help"
      //    run all test classes (with logging):         "TestSuite.exe"
      //    print all test classes:                      "TestSuite.exe -classes"
      //    run one test class with QtTest parameters:   "TestSuite.exe testClass [options] [testfunctions[:testdata]]...
      if (QCoreApplication::arguments().size() > 1 && QCoreApplication::arguments()[1] == "-help")
      {
         qDebug() << "Usage:";
         qDebug().noquote() << "run all test classes (with logging):\t\t" << qAppName();
         qDebug().noquote() << "print all test classes:\t\t\t\t" << qAppName() << "-classes";
         qDebug().noquote() << "run one test class with QtTest parameters:\t" << qAppName() << "testClass [options][testfunctions[:testdata]]...";
         qDebug().noquote() << "get more help for running one test class:\t" << qAppName() << "testClass -help";
         exit(0);
      }

      foreach(QObject * test, m_tests)
      {
         QStringList arguments;
         QString testName = test->metaObject()->className();

         if (QCoreApplication::arguments().size() > 1)
         {
            if (QCoreApplication::arguments()[1] == "-classes")
            {
               // only print test classes
               qDebug().noquote() << testName;
               continue;
            }
            else
               if (QCoreApplication::arguments()[1] != testName)
               {
                  continue;
               }
               else
               {
                  arguments = QCoreApplication::arguments();
                  arguments.removeAt(1);
               }
         }
         else
         {
            arguments.append(QCoreApplication::arguments()[0]);
            // log to console
            arguments.append("-o"); arguments.append("-,txt");
            // log to file as TXT
            arguments.append("-o"); arguments.append(mTestLogFolder % "/" % testName % ".log,txt");
            // log to file as XML
            arguments.append("-o"); arguments.append(mTestLogFolder % "/" % testName % ".xml,xunitxml");
         }
         m_overallResult |= QTest::qExec(test, arguments);
      }
   }

   QList<QObject *> m_tests;
   int m_overallResult;
   const QString mTestLogFolder = "testLogs";
};

#endif // TESTRUNNER_H

独自のコード

#include "testrunner.h"
#include "test1" 
...

#include <QDebug>

int main(int argc, char * argv[]) 
{
    TestRunner testRunner;

    //your QTest compatible class here
    testRunner.addTest(new Test1);
    testRunner.addTest(new Test2);
    ...

    bool pass = testRunner.runTests(argc, argv);
    qDebug() << "Overall result: " << (pass ? "PASS" : "FAIL");

    return pass?0:1;
}
あなたはQtのを使用している場合、ISは、UIをテストするための施設を持っており、使用するのは簡単ですので、

、私は、QtTestを使用することをお勧めします。

あなたがQtCoreを使用する場合は、

、あなたはおそらくSTLなしで行うことができます。私は頻繁にSTLの対応よりも使いやすくQtのクラスを見つけます。

って遊びます。の利用試験QtTestがあることができましたすべてのUI開発できます。ご利用の場合はVisual Studio2012びフラッシングを行い、 Googleアダプター試験 きVSであることを認識せざるを得試験としてその試験は以下のように変更しました。これは開発者が利用できるようにしてんのこれからのコードでGoogleの試験は携帯また、追加の試験にLinux。

今度は、今後人の追加支援のためのC++の同時検査ツールのC#て、 NCrunch, ジャイルズContinuousTests.

もちろん、感じるかもしれませんが、誰に書き込み別のアダプター VS2012を追加するQtTest支援の試験アダプターの場合は、この利点があります。だが、ここにありますブログ オーサリング新作は単体テスト用アダプター.

QtTestフレームワークを使用してVisual Studioのテストアダプター・ツールのサポートについては、このVisual Studioの拡張:<のhref = "https://visualstudiogallery.msdn.microsoft.com/cc1fcd27-4e58-4663-951f-fb02d9ff3653" のrel =」 nofollowを "> https://visualstudiogallery.msdn.microsoft.com/cc1fcd27-4e58-4663-951f-fb02d9ff3653 の

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top