Kapitel 2: Datengesteuertes Testen

In diesem Kapitel wird gezeigt, wie man einen Test mehrfach mit unterschiedlichen Testdaten ausführt.

Bisher haben wir die Daten, die wir testen wollten, fest in unsere Testfunktion codiert. Wenn wir weitere Testdaten hinzufügen, könnte die Funktion wie folgt aussehen:

QCOMPARE(QString("hello").toUpper(), QString("HELLO"));
QCOMPARE(QString("Hello").toUpper(), QString("HELLO"));
QCOMPARE(QString("HellO").toUpper(), QString("HELLO"));
QCOMPARE(QString("HELLO").toUpper(), QString("HELLO"));

Um zu verhindern, dass die Funktion mit sich wiederholendem Code überladen wird, unterstützt Qt Test das Hinzufügen von Testdaten zu einer Testfunktion. Dazu müssen wir lediglich einen weiteren privaten Slot zu unserer Testklasse hinzufügen:

class TestQString: public QObject
{
    Q_OBJECT

private slots:
    void toUpper_data();
    void toUpper();
};

Schreiben der Datenfunktion

Die einer Testfunktion zugeordnete Datenfunktion hat den Zusatz _data. Unsere Datenfunktion sieht wie folgt aus:

void TestQString::toUpper_data()
{
    QTest::addColumn<QString>("string");
    QTest::addColumn<QString>("result");

    QTest::newRow("all-lower") << "hello" << "HELLO";
    QTest::newRow("mixed")     << "Hello" << "HELLO";
    QTest::newRow("all-upper") << "HELLO" << "HELLO";
}

Zunächst definieren wir die beiden Elemente unserer Testtabelle mithilfe der Funktion QTest::addColumn(): eine Testzeichenfolge und das erwartete Ergebnis der Anwendung der Funktion QString::toUpper() auf diese Zeichenfolge.

Dann fügen wir mit der Funktion QTest::newRow() einige Daten in die Tabelle ein. Wir können auch QTest::addRow() verwenden, wenn wir einige Daten im Zeilennamen formatieren müssen, z. B. wenn wir viele Datenzeilen iterativ erzeugen. Jede Datenzeile wird zu einer eigenen Zeile in der Testtabelle.

QTest::newRow() nimmt ein Argument entgegen: einen Namen, der mit dem Datensatz verknüpft wird und im Testprotokoll zur Identifizierung der Datenzeile verwendet wird. QTest::addRow() nimmt eine (printf-style) Formatzeichenkette entgegen, gefolgt von den Parametern, die anstelle der Formatierungstoken in der Formatzeichenkette dargestellt werden sollen. Dann streamen wir den Datensatz in die neue Tabellenzeile. Zuerst eine beliebige Zeichenfolge und dann das erwartete Ergebnis der Anwendung der Funktion QString::toUpper() auf diese Zeichenfolge.

Sie können sich die Testdaten als eine zweidimensionale Tabelle vorstellen. In unserem Fall hat sie zwei Spalten namens string und result und drei Zeilen. Darüber hinaus sind jeder Zeile ein Name und ein Index zugeordnet:

indexNameZeichenfolgeErgebnis
0ganz-unten"hallo"HALLO
1gemischt"Hallo"HALLO
2ganz oben"HELLO"HELLO

Wenn Daten in die Zeile strömen, wird jedes Datum auf Übereinstimmung mit dem Typ der Spalte geprüft, deren Wert es liefert. Schlägt eine Überprüfung fehl, wird der Test abgebrochen.

Die Namen von Zeilen und Spalten in der Datentabelle einer Testfunktion sollten eindeutig sein: wenn zwei Zeilen einen Namen teilen oder zwei Spalten einen Namen teilen, wird (seit Qt 6.5) eine Warnung ausgegeben. Siehe qWarning() für die Behandlung von Warnungen als Fehler und Test für Warnungen, um Ihre Tests von anderen Warnungen zu befreien.

Umschreiben der Testfunktion

Unsere Testfunktion kann nun umgeschrieben werden:

void TestQString::toUpper()
{
    QFETCH(QString, string);
    QFETCH(QString, result);

    QCOMPARE(string.toUpper(), result);
}

Die Funktion TestQString::toUpper() wird dreimal ausgeführt, einmal für jeden Eintrag in der Testtabelle, die wir mit der zugehörigen Funktion TestQString::toUpper_data() erstellt haben.

Zunächst werden die beiden Elemente des Datensatzes mit dem Makro QFETCH() abgerufen. QFETCH() nimmt zwei Argumente entgegen: Den Datentyp des Elements und den Namen des Elements. Dann führen wir den Test mit dem Makro QCOMPARE() durch.

Dieser Ansatz macht es sehr einfach, dem Test neue Daten hinzuzufügen, ohne den Test selbst zu ändern.

Vorbereiten der eigenständigen ausführbaren Datei

Um unseren Testfall zu einer eigenständigen ausführbaren Datei zu machen, werden die folgenden zwei Zeilen benötigt:

QTEST_MAIN(TestQString)
#include "testqstring.moc"

Wie zuvor wird das QTEST_MAIN()-Makro zu einer einfachen main()-Methode erweitert, die alle Testfunktionen ausführt, und da sich sowohl die Deklaration als auch die Implementierung unserer Testklasse in einer .cpp-Datei befinden, müssen wir auch die generierte moc-Datei einschließen, damit die Introspektion von Qt funktioniert.

Erstellen der ausführbaren Datei

Sie können die ausführbare Datei des Testfalls mit CMake oder qmake erstellen.

Bauen mit CMake

Konfigurieren Sie Ihre Build-Einstellungen in Ihrer CMakeLists.txt-Datei:

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

cmake_minimum_required(VERSION 3.16)
project(tutorial2 LANGUAGES CXX)

find_package(Qt6 REQUIRED COMPONENTS Core Gui Test Widgets)

qt_standard_project_setup()

qt_add_executable(tutorial2
    testqstring.cpp
)

set_target_properties(tutorial2 PROPERTIES
    WIN32_EXECUTABLE TRUE
    MACOSX_BUNDLE TRUE
)

target_link_libraries(tutorial2 PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Test
    Qt6::Widgets
)

install(TARGETS tutorial2
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

qt_generate_deploy_app_script(
    TARGET tutorial2
    OUTPUT_SCRIPT deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

Führen Sie dann von der Befehlszeile aus entweder cmake aus oder verwenden Sie das Skript qt-cmake, das sich in Qt-prefix/<version>/<platform>/bin/qt-cmake befindet:

<Qt-prefix>/<version>/<platform>/bin/qt-cmake <source-dir> <build-dir> -G Ninja

Führen Sie dann Ihr bevorzugtes Generatorwerkzeug aus, um die ausführbare Datei zu erstellen. Hier verwenden wir Ninja:

ninja

Bauen mit qmake

Konfigurieren Sie Ihre Build-Einstellungen in Ihrer .pro Datei:

QT += widgets testlib

SOURCES = testqstring.cpp

# install
target.path = $$[QT_INSTALL_EXAMPLES]/qtestlib/tutorial2
INSTALLS += target

Führen Sie anschließend qmake und schließlich make aus, um Ihre ausführbare Datei zu erstellen:

qmake
make

Ausführen der ausführbaren Datei

Wenn Sie die resultierende ausführbare Datei ausführen, sollten Sie die folgende Ausgabe erhalten:

********* Start testing of TestQString *********
Config: Using QtTest library %VERSION%, Qt %VERSION%
PASS   : TestQString::initTestCase()
PASS   : TestQString::toUpper(all-lower)
PASS   : TestQString::toUpper(mixed)
PASS   : TestQString::toUpper(all-upper)
PASS   : TestQString::cleanupTestCase()
Totals: 5 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of TestQString *********

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.