Frage

begann ich einige Tests mit Qt-Unit-Test-System zu schreiben.

Wie Sie in der Regel die Tests organisieren? Es ist eine Test-Klasse pro Modul Klasse, oder haben Sie das gesamte Modul mit einer einzigen Test-Klasse testen? Qt docs schlagen die erste Strategie zu folgen.

Ich möchte für einen Modultest schreiben. Das Modul bietet nur eine Klasse, die von dem Modul Benutzer verwendet werden wird, aber es gibt eine Menge von Logik in anderen Klassen abstrahiert, was ich möchte auch zu testen, neben der öffentliche Klasse testen.

Das Problem ist, dass Qt vorgeschlagene Art und Weise zum Ausführen von Tests der QTEST_MAIN Makro beteiligt: ??

QTEST_MAIN(TestClass)
#include "test_class.moc"

und schließlich ein Testprogramm in der Lage ist nur ein Test-Klasse zu testen. Und es saugt irgendwie Testprojekte für jede einzelne Klasse im Modul zu erstellen.

Natürlich könnte man einen Blick auf die QTEST_MAIN Makro nehmen, schreiben sie und andere Testklassen laufen. Aber es ist etwas, das die Box klappt?

Bisher ich es von Hand:

#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);
}
War es hilfreich?

Lösung

Ja, biss QTest Kräfte seltsame Teststruktur und ist in der Regel schlechter als Google Test / Mock-Framework. Bei einem Projekt bin ich gezwungen QTest (Client-Anforderung) zu verwenden, und hier ist, wie ich es verwenden:

  1. ich alle Test kompilieren zusammen als subdir Vorlage Projekt
  2. Um neue Tests zu erleichtern die Erstellung, ich habe eine Menge Projektkonfiguration teilen, indem common.pri Datei mit I gehören in jedem Test .proDatei
  3. Wenn möglich, ich teile die Objektdateien Verzeichnis compilation
  4. beschleunigen
  5. Ich betreibe sie alle mit einem Batch + awk + sed-Skript.

Diese vier Punkte Einrichten ist sehr einfach und macht Gebrauch von QTest fast angenehm. Haben Sie einige Probleme mit mehreren Tests ausgeführt wird, die durch die Config nicht gelöst werden oben beschrieben?

PS:. Ausführen von Tests, wie Sie tun, das heißt Aufruf mehr QTest :: qExec verursacht Probleme mit -o Befehlszeilenoption - Sie werden nur Ergebnisse für die letzte Klasse getestet bekommen

Andere Tipps

Im Zusammenhang mit der Antwort gepostet von @cjhuitt

Dies ist ein Beispiel, das die Notwendigkeit des manuellen Aufruf jedes Testobjekt

entfernt

Ich VERSUCHEN Dinge wie dies zu vermeiden:

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

Meine Lösung ist der Test erben von einer Basisklasse Objekte zu lassen, die sich auf eine statische Liste fügt Das Hauptprogramm führt dann alle Testobjekte in dieser Liste. Auf diese Weise keine der Unterstützung Framework-Code geändert werden muss. Die einzigen Dinge, die Änderung sind die Testklassen selbst.

Hier ist, wie ich es tun:

qtestsuite.h - Basisklasse für die Testobjekte

#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 - führt die Tests

#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 - ein Beispiel Testobjekt, erstellen mehrere dieser

#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"

auch zu schaffen, die .pro-Datei

qmake -project "CONFIG += qtestlib"

In unserem Setup mit QTest, haben wir ein paar Dinge zu machen, schöner.

  • Definieren Sie eine Unterklasse von QObject, die als Basisklasse für jede neue Unit-Test-Klasse verwendet wird.
  • Sie im Konstruktor für diese Klasse, fügen wir die Instanz des Tests auf eine statische Liste von Tests, und in dem destructor wir es entfernen.
  • Wir haben dann eine statische Funktion, die Schleifen durch die Tests und läuft sie QTest::qExec() verwenden. (Wir reichern sich die Werte jedes Mal zurück, und Rückkehr, die von unserer Funktion.)
  • main() nennt diese Funktion, und gibt das Ergebnis als Erfolg / Misserfolg.
  • Schließlich in der Übersetzungseinheit des spezifischen Tests selbst, wir sind in der Regel eine statische Instanz dieser Klasse.

Dieses Setup bedeutet, dass die Klasse vor main() instanziiert wird, ausgeführt wird, so wird es, wenn die Hauptläufe in der Liste der Klassen Test hinzugefügt werden. Das Framework setzt voraus, dass Sie nur richtig Klasse erben müssen, und eine statische Instanz instanziiert, wenn Sie wollen immer ausführen.

Wir gelegentlich auch andere optionale Tests erstellen, die basierend auf Befehlszeilenoptionen hinzugefügt werden.

Normalerweise organisieren I-Tests mit einer Test ausführbare pro Klasse unter Test.

und schließlich ein Testprogramm Lage nur einen Test zum Testen Klasse.

Dies ist eine gute Sache. Es isoliert die Tests voneinander, Dinge wie ein Absturz in einem Test blockiert alle anderen Tests zu verhindern. Das Crash könnte durch eine gemeinsame Komponente in mehreren Klassen im Test verursacht werden. Das Muster der Ausfälle würden Sie dann kippen, um die zugrunde liegende Ursache des Problems ab. Grundsätzlich haben Sie eine bessere Diagnoseinformationen für Fehler, wenn die Tests unabhängig voneinander sind.

Machen Sie es einfach mehrere ausführbare Dateien einzurichten und jeden Test separat ausgeführt werden. Verwenden Sie einen Testläufer Laich aus allen Testverfahren.

Update:

Ich habe meine Meinung zu diesem Thema etwas geändert. Sobald Sie ein großes Programm mit vielen Tests haben, wird hunderte von Test Executables Verknüpfung sehr langsam. Meine neue Präferenz ist es, alle die Tests für eine Bibliothek in eine ausführbare Datei und Wahl zu stellen, die Tests auf die Probe ausführbare bestanden mit Befehlszeilenargumente aufzurufen.

Dass verkürzt sich die Anzahl der ausführbaren Dateien von Hunderten von Dutzenden, behält aber die Vorteile von Tests separat ausgeführt werden.

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