Frage

Ich beginne gerade ein neues Projekt, das auch eine plattformübergreifende GUI benötigt, und wir haben Qt als GUI-Framework gewählt.

Wir brauchen eine Einheit-Test-Framework, auch. Bis vor etwa einem Jahr haben wir eine selbst entwickelte Einheit-Test-Framework für C ++ - Projekte, aber wir werden der Übergang jetzt mit Google-Test für neue Projekte

.

hat jemand Erfahrung mit der Verwendung von Google-Test für Qt-Anwendungen? Ist QtTest / QTestLib eine bessere Alternative?

Ich bin immer noch nicht sicher, wie viel wollen wir Qt in den Nicht-GUI-Teilen des Projektes verwenden - wir wahrscheinlich nur Verwendung STL / Boost in dem Kern-Code mit einer kleinen Schnittstelle zur Qt-basierten GUI bevorzugen .

EDIT: Es sieht aus wie viele sind auf QtTest gelehnt. Gibt es jemand, keine Erfahrung hat mit der Integration dieses mit einem kontinuierlichen Integrationsserver? Auch wäre es mir scheinen, dass eine separate Anwendung für jeden neuen Testfall viel Reibung verursachen würde handhaben zu müssen. Gibt es eine gute Möglichkeit, das zu lösen? Does Qt Creator haben eine gute Möglichkeit, solche Testfälle von der Handhabung oder würden Sie benötigen ein Projekt pro Testfall haben?

War es hilfreich?

Lösung

Ich weiß nicht, dass QTestLib ist „besser“ als ein Rahmen für eine andere so allgemein. Es ist eine Sache, dass es funktioniert gut, und das ist bietet eine gute Möglichkeit zu testen, Qt-basierte Anwendungen.

Sie könnten QTest in Ihre neue Google-Test basierten Setup integrieren. Ich habe es nicht ausprobiert, aber je nachdem, wie QTestLib architected ist, wie es scheint, ist es nicht zu kompliziert wäre.

geschrieben Tests mit reinem QTestLib haben eine -xml Option, dass Sie, zusammen mit einigen XSLT-Transformationen nutzen könnten, um das benötigte Format für eine kontinuierliche Integration Server zu konvertieren. Allerdings hängt viel davon ab, welche CI-Server Sie gehen mit. Ich könnte mir vorstellen, das gleiche gilt für Gtest.

Ein einzelner Test-App pro Testfall nie viel Reibung für mich verursacht, aber das hängt von einem Build-System, die einen guten Job für die Verwaltung der Gebäude und die Ausführung der Testfälle tun würde.

Ich weiß nicht, von irgendetwas in Qt Creator, die ein separates Projekt pro Testfall erfordern würde, aber es seit dem letzten Mal geändert haben, konnte ich auf Qt Creator sah.

Ich würde auch vorschlagen, mit QtCore kleben und bleibt weg von der STL. Mit QtCore im gesamten macht mit den GUI-Bits zu tun, die die Qt-Datentypen einfacher erfordern. Sie werden nicht über die Umwandlung von einem Datentyp in einer anderen in diesem Fall zu kümmern.

Andere Tipps

Sie müssen keine separaten Tests Anwendungen erstellen. verwenden qExec nur in einer unabhängigen main () Funktion ähnlich wie diese:

int main(int argc, char *argv[])
{
    TestClass1 test1;
    QTest::qExec(&test1, argc, argv);

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

    // ...

    return 0;
}

Damit werden alle Testmethoden in jeder Klasse in einer Charge auszuführen.

Ihre Testklasse H-Dateien würde wie folgt aussehen:

class TestClass1 : public QObject
{
Q_OBJECT

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

Leider ist diese Einstellung nicht wirklich gut beschrieben in der Qt-Dokumentation, obwohl es für viele Menschen sehr nützlich zu sein scheint.

Joes Antwort anzuhängen.

Hier ist eine kleiner Header I Verwendung (testrunner.h), eine Utility-Klasse Laichen eine Ereignisschleife enthält (das ist zum Beispiel notwendig, um Test Warteschlange Signal-Slot-Verbindungen und Datenbanken) und QTest-kompatible Klassen „läuft“:

#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

Verwenden Sie es wie folgt aus:

#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;
}

begann ich mit QtTest für meine app weg und sehr, sehr schnell begann mit ihm laufen in Grenzen. Die beiden Hauptprobleme waren:

1) laufen Meine Tests sehr schnell - schnell genug, dass der Kopf eine ausführbare Datei zu laden, eine Q (Core) Anwendung einrichten (falls erforderlich) usw. oft Zwerge die Laufzeit der Tests selbst! jede ausführbare Datei verknüpfen viel Zeit in Anspruch nimmt, auch.

Der Aufwand einfach weiter so mehr zunehmen und mehr Klassen wurden hinzugefügt, und es wurde bald ein Problem - eines der Ziele von Unit-Tests sind ein Sicherheitsnetz haben, dass läuft so schnell, dass es nicht zu einer Belastung überhaupt ist, und dies wurde immer schnell nicht der Fall. Die Lösung besteht darin, mehrere Testsuiten in eine ausführbare Datei zu glob, und während (wie oben gezeigt) wird dies meist tun können, ist es nicht unterstützt und wichtige Einschränkungen.

2) Keine Befestigung Unterstützung -. Ein Deal-Breaker für mich

So nach einer Weile, ich Google-Test eingeschaltet - es ist eine weit mehr featureful und anspruchsvolle Komponententestframework (vor allem, wenn sie mit Google Mock verwendet) und löst 1) und 2), und darüber hinaus können Sie immer noch leicht die Verwendung handlich QTestLib Funktionen wie QSignalSpy und Simulation von GUI-Ereignissen usw. Es ist ein bisschen wie ein Schmerz zu Schalter war, aber zum Glück war das Projekt nicht zu weit fortgeschritten, und viele der Änderungen automatisiert werden können.

Persönlich werde ich nicht QtTest über Google-Test für zukünftige Projekte verwenden -. Wenn Angebote keine wirklichen Vorteile, dass ich sehen kann, und wichtige Nachteile

Warum nicht die Komponententests unter Verwendung von Rahmen in Qt enthalten? Ein Beispiel:. QtTestLib Tutorial

I-Einheit getestet unsere Bibliotheken mit Gtest und QSignalSpy . Verwenden QSignalSpy zu fangen Signale. Sie können Slots direkt anrufen (wie normale Methoden), um sie zu testen.

QtTest ist meist nützlich für Teile, die die Prüfung Qt Ereignisschleife / Signal Dispatching erfordern. Es ist in einer Weise, dass jeder Testfall eine separate ausführbare Datei erfordert, so sollte es nicht in Konflikt mit jedem Rahmen bestehenden Test für den Rest der Anwendung verwendet wird.

(Btw, ich sehr empfehlen die Verwendung von QtCore auch für Nicht-GUI-Teile der Anwendungen. Es ist viel schöner zu arbeiten.)

Zur Erweiterung mlvljr ist und Joe-Lösung können wir sogar komplette QtTest Optionen pro Testklasse unterstützen und immer noch alle in einer Charge und Protokollierung ausführen:

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]]...

Header

#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

eigener Code

#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;
}

Wenn Sie Qt verwenden, würde ich empfehlen, QtTest verwenden, weil sich Einrichtungen hat die Benutzeroberfläche zu testen und ist einfach zu bedienen.

Wenn Sie QtCore verwenden, können Sie wahrscheinlich ohne STL tun. Ich häufig die Qt-Klassen finden einfacher zu bedienen als die STL-Pendants.

Ich habe zu spielen gerade mit diesem um. Der Hauptvorteil der Verwendung von Google-Test über QtTest für uns ist, dass wir in Visual Studio all unsere UI-Entwicklung zu tun. Wenn Sie Visual Studio verwenden 2012 und installieren Sie das Google Prüfadapter kann erhalten VS die Tests und sie in ihrem Test Explorer zu erkennen. Dies ist ideal für Entwickler in der Lage sein zu verwenden, wie sie Code schreiben, und weil Google-Test tragbar ist, wir können auch die Tests bis zum Ende unserer Linux Build hinzuzufügen.

Ich hoffe, in der Zukunft, dass jemand der Unterstützung für C ++ zu einem der gleichzeitigen Test-Tool hinzufügen wird, dass C #, wie NCrunch , Giles und ContinuousTests .

Natürlich finden Sie vielleicht jemand einen anderen Adapter für VS2012 schreibt die QtTest Unterstützung Prüfadapter wobei dieser Vorteil weg geht fügt! Wenn jemand daran interessiert ist, gibt es eine gute Blog-Post eine neue Visual Studio-Einheit Prüfadapter Authoring.

Für Visual Studio Testadapter Werkzeugträger mit der QtTest Rahmen Verwendung dieser Visual Studio-Erweiterung: https://visualstudiogallery.msdn.microsoft.com/cc1fcd27-4e58-4663-951f-fb02d9ff3653

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top