Sur cette page

Qt Test Présentation générale

Qt Test est un framework destiné aux tests unitaires d'applications et de bibliothèques basées sur Qt. Qt Test offre toutes les fonctionnalités couramment présentes dans les frameworks de tests unitaires, ainsi que des extensions permettant de tester les interfaces utilisateur graphiques.

Qt Test est conçu pour faciliter l'écriture de tests unitaires pour les applications et bibliothèques basées sur Qt :

FonctionnalitéDétails
LégerQt Test comprend environ 6 000 lignes de code et 60 symboles exportés.
AutonomeQt Test ne nécessite que quelques symboles du module « Qt Core » pour les tests hors interface graphique.
Tests rapidesQt Test ne nécessite aucun exécuteur de tests spécifique ; aucune inscription particulière n’est requise pour les tests.
Tests pilotés par les donnéesUn test peut être exécuté plusieurs fois avec des données de test différentes.
Tests d'interface graphique de baseQt Test offrent des fonctionnalités de simulation de la souris et du clavier.
Analyses comparativesQt Test prend en charge l'analyse comparative et propose plusieurs back-ends de mesure.
Compatible avec les IDEQt Test génère des messages pouvant être interprétés par Qt Creator, Visual Studio et KDevelop.
Sécurité des threadsLe signalement des erreurs est sûr pour les threads et atomique.
Sécurité des typesL'utilisation intensive de modèles permet d'éviter les erreurs introduites par les transtypages implicites.
Facilement extensibleDes types personnalisés peuvent facilement être ajoutés aux données de test et aux résultats des tests.

Vous pouvez utiliser l’assistant « Qt Creator » pour créer un projet contenant des Qt Tests, puis les compiler et les exécuter directement depuis Qt Creator. Pour plus d’informations, consultez Qt Creator: Compiler et exécuter des tests.

Création d'un test

Pour créer un test, créez une sous-classe de ` QObject ` et ajoutez-y un ou plusieurs slots privés. Chaque slot privé correspond à une fonction de test dans votre test. La méthode ` QTest::qExec()` permet d'exécuter toutes les fonctions de test de l'objet test.

De plus, vous pouvez définir les slots privés suivants, qui ne sont pas traités comme des fonctions de test. Lorsqu’ils sont présents, ils sont exécutés par le framework de test et peuvent être utilisés pour initialiser et nettoyer soit le test dans son ensemble, soit la fonction de test en cours.

  • initTestCase() sera appelée avant l’exécution de la première fonction de test.
  • initTestCase_data() sera appelée pour créer une table de données de test globale.
  • cleanupTestCase() sera appelée après l'exécution de la dernière fonction de test.
  • init() sera appelée avant l'exécution de chaque fonction de test.
  • cleanup() sera appelée après chaque fonction de test.

Utilisez ` initTestCase() ` pour préparer le test. Chaque test doit laisser le système dans un état utilisable, afin qu’il puisse être exécuté à plusieurs reprises. Les opérations de nettoyage doivent être gérées dans ` cleanupTestCase()`, afin qu’elles soient exécutées même si le test échoue.

Utilisez init() pour préparer une fonction de test. Chaque fonction de test doit laisser le système dans un état utilisable, afin qu’elle puisse être exécutée à plusieurs reprises. Les opérations de nettoyage doivent être gérées dans cleanup(), afin qu’elles soient exécutées même si la fonction de test échoue et se termine prématurément.

Vous pouvez également utiliser le principe RAII (Resource Acquisition Is Initialization), avec des opérations de nettoyage appelées dans les destructeurs, afin de garantir qu’elles s’exécutent lorsque la fonction de test revient et que l’objet sort de la portée.

Si l’ initTestCase() échoue, aucune fonction de test ne sera exécutée. Si l’ init() échoue, la fonction de test suivante ne sera pas exécutée ; le test passera à la fonction de test suivante.

Exemple :

class MyFirstTest : public QObject
{
    Q_OBJECT

private:
    bool myCondition()
    {
        return true;
    }

private slots:
    void initTestCase()
    {
        qDebug("Called before everything else.");
    }

    void myFirstTest()
    {
        QVERIFY(true) ; // vérifier qu'une condition est remplie
        QCOMPARE(1, 1) ; // comparer deux valeurs
    }

   void mySecondTest()
    {
        QVERIFY(myCondition());
        QVERIFY(1 != 2);
    }

    void cleanupTestCase()
    {
        qDebug("Called after myFirstTest and mySecondTest.");
    }
};

Enfin, si la classe de test dispose d’une méthode statique publique void initMain(), celle-ci est appelée par les macros QTEST_MAIN avant l’instanciation de l’objet QApplication. Cette fonctionnalité a été ajoutée dans la version 5.14.

Pour plus d’exemples, consultez le tutoriel sur l’Qt Test .

Augmentation du délai d’expiration des fonctions de test

QtTest limite la durée d’exécution de chaque test afin de détecter les boucles infinies et autres bogues similaires. Par défaut, tout appel à une fonction de test sera interrompu au bout de cinq minutes. Pour les tests pilotés par les données, cette règle s’applique à chaque appel doté d’une balise de données distincte. Ce délai d'expiration peut être configuré en définissant la variable d'environnement ` QTEST_FUNCTION_TIMEOUT ` sur le nombre maximal de millisecondes acceptable pour un seul appel. Si un test dure plus longtemps que le délai d'expiration configuré, il est interrompu et la méthode ` qFatal() ` est appelée. En conséquence, le test s'interrompt par défaut, comme s'il avait planté.

Pour définir QTEST_FUNCTION_TIMEOUT depuis la ligne de commande sous Linux ou macOS, saisissez :

QTEST_FUNCTION_TIMEOUT=900000
export QTEST_FUNCTION_TIMEOUT

Sous Windows :

SET QTEST_FUNCTION_TIMEOUT=900000

Lancez ensuite le test dans cet environnement.

Vous pouvez également définir la variable d'environnement par programmation dans le code de test lui-même, par exemple en appelant, depuis la méthode spéciale initMain() de votre classe de test :

qputenv("QTEST_FUNCTION_TIMEOUT", "900000");

Pour calculer une valeur appropriée pour le délai d'expiration, vérifiez la durée habituelle du test et déterminez jusqu'à quelle durée il peut s'étendre sans que cela ne soit le signe d'un problème. Convertissez ce délai supplémentaire en millisecondes pour obtenir la valeur du délai d'expiration. Par exemple, si vous estimez qu'un test qui dure plusieurs minutes pourrait raisonnablement prendre jusqu'à vingt minutes, notamment sur une machine lente, multipliez 20 * 60 * 1000 = 1200000 et définissez la variable d'environnement sur 1200000 au lieu de 900000 ci-dessus.

Création d'un test

Vous pouvez créer un exécutable contenant une classe de test qui teste généralement une classe de code de production. Cependant, vous souhaiterez généralement tester plusieurs classes d’un projet en exécutant une seule commande.

Consultez la section « Écrire un test unitaire » pour obtenir des explications étape par étape.

Compilation avec CMake et CTest

Vous pouvez utiliser CMake et CTest pour créer un test. CTest vous permet d’inclure ou d’exclure des tests en fonction d’une expression régulière appliquée au nom du test. Vous pouvez également attribuer la propriété « LABELS » à un test ; CTest pourra alors inclure ou exclure des tests en fonction de ces étiquettes. Toutes les cibles étiquetées seront exécutées lorsque la cible « test » sera appelée en ligne de commande.

Remarque : sous Android, si un seul appareil ou émulateur est connecté, les tests s’exécuteront sur cet appareil. Si plusieurs appareils sont connectés, définissez la variable d’environnement ANDROID_DEVICE_SERIAL sur le numéro de série ADB de l’appareil sur lequel vous souhaitez exécuter les tests.

CMake présente plusieurs autres avantages. Par exemple, le résultat d’une exécution de test peut être publié sur un serveur web à l’aide de CDash, et ce, sans pratiquement aucun effort.

CTest s'adapte à des frameworks de tests unitaires très différents et fonctionne dès l'installation avec QTest.

Voici un exemple de fichier CMakeLists.txt qui spécifie le nom du projet et le langage utilisé (ici, mytest et C++), les modules Qt requis pour la compilation du test (Qt Test) et les fichiers inclus dans le test (tst_mytest.cpp).

project(mytest LANGUAGES CXX)

find_package(Qt6 REQUIRED COMPONENTS Test)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOMOC ON)

enable_testing(true)

qt_add_executable(mytest tst_mytest.cpp)
add_test(NAME mytest COMMAND mytest)

target_link_libraries(mytest PRIVATE Qt::Test)

Pour plus d’informations sur les options disponibles, consultez la section « Compilation avec CMake ».

Compilation avec qmake

Si vous utilisez qmake comme outil de compilation, il vous suffit d'ajouter ce qui suit à votre fichier de projet :

QT += testlib

Si vous souhaitez exécuter les tests via make check, ajoutez la ligne suivante :

CONFIG += testcase

Pour empêcher l’installation du test sur votre cible, ajoutez la ligne suivante :

CONFIG += no_testcase_installs

Consultez le manuel de qmake pour plus d’informations sur l’ make check.

Compilation avec d'autres outils

Si vous utilisez d’autres outils de compilation, veillez à ajouter l’emplacement des fichiers d’en-tête Qt Test à votre chemin d’inclusion (généralement include/QtTest dans votre répertoire d’installation de Qt). Si vous utilisez une version finale de Qt, liez votre test à la bibliothèque QtTest. Pour les versions de débogage, utilisez QtTest_debug.

Qt Test Arguments de ligne de commande

Syntaxe

La syntaxe permettant d'exécuter un autotest se présente sous la forme simple suivante :

testname [options] [testfunctions[:testdata]]...

Remplacez « testname » par le nom de votre exécutable. « testfunctions » peut contenir les noms des fonctions de test à exécuter. Si aucune « testfunctions » n’est fournie, tous les tests sont exécutés. Si vous ajoutez le nom d’une entrée de « testdata », la fonction de test ne sera exécutée qu’avec ces données de test.

Par exemple :

/myTestDirectory$ testQString toUpper

Exécute la fonction de test nommée toUpper avec toutes les données de test disponibles.

/myTestDirectory$ testQString toUpper toInt:zero

Exécute la fonction de test toUpper avec toutes les données de test disponibles, ainsi que la fonction de test toInt avec la ligne de données de test nommée zero (si les données de test spécifiées n'existent pas, le test associé échouera et les balises de données disponibles seront signalées).

/myTestDirectory$ testMyWidget -vs -eventdelay 500

Exécute le test de la fonction testMyWidget, affiche chaque émission de signal et attend 500 millisecondes après chaque événement simulé de souris ou de clavier.

Options

Options de journalisation

Les options de ligne de commande suivantes déterminent la manière dont les résultats des tests sont présentés :

  • -o nom_fichier,format
    Writes output to the specified file, in the specified format (one of txt, csv, junitxml, xml, lightxml, teamcity or tap). Use the special filename - (hyphen) to log to standard output.
  • -o filename
    Écrit les résultats dans le fichier spécifié.
  • -txt
    Affiche les résultats en texte brut.
  • -csv
    Affiche les résultats sous forme de valeurs séparées par des virgules (CSV), adaptées à l'importation dans des tableurs. Ce mode ne convient qu'aux tests de performance, car il supprime les messages habituels de réussite ou d'échec.
  • -junitxml
    Affiche les résultats sous forme de document XML JUnit.
  • -xml
    Affiche les résultats sous forme de document XML.
  • -lightxml
    Affiche les résultats sous forme de flux de balises XML.
  • -teamcity
    Affiche les résultats au format TeamCity.
  • -tap
    Affiche les résultats au format TAP ( Test Anything Protocol ).

La première version de l’option « -o » peut être répétée afin d’enregistrer les résultats des tests dans plusieurs formats, mais une seule instance de cette option peut enregistrer les résultats des tests vers la sortie standard.

Si la première version de l’option -o est utilisée, il ne faut pas utiliser la deuxième version de l’option -o, ni les options -txt, -xml, -lightxml, -teamcity, -junitxml ou -tap.

Si aucune des deux versions de l'option « -o » n'est utilisée, les résultats des tests seront affichés sur la sortie standard. Si aucune option de format n'est utilisée, les résultats des tests seront affichés en texte brut.

Options de détail du journal de test

Les options de ligne de commande suivantes permettent de contrôler le niveau de détail des journaux de test :

    • -silent
      Sortie silencieuse ; n'affiche que les erreurs fatales, les échecs de test et un minimum de messages d'état.
    • -v1
      Sortie détaillée ; indique le moment où chaque fonction de test est exécutée. (Cette option n'affecte que la sortie en texte brut.)
    • -v2
      Extended verbose output; shows each QCOMPARE() and QVERIFY(). (This option affects all output formats and implies -v1 for plain text output.)
    • -vs
      Affiche tous les signaux émis ainsi que les appels de slot résultant de ces signaux. (Cette option s'applique à tous les formats de sortie.)

    Options de test

    Les options de ligne de commande suivantes influencent la manière dont les tests sont exécutés :

    • -functions
      Affiche toutes les fonctions de test disponibles dans le test, puis quitte.
    • -datatags
      Affiche toutes les balises de données disponibles dans le test. Une balise de données globale est précédée de « __global__ ».
    • -eventdelay ms
      If no delay is specified for keyboard or mouse simulation (QTest::keyClick(), QTest::mouseClick() etc.), the value from this parameter (in milliseconds) is substituted.
    • -keydelay ms
      Comme l'option -eventdelay, mais n'affecte que la simulation du clavier et non celle de la souris.
    • -mousedelay ms
      Comme l'option -eventdelay, mais n'affecte que la simulation de la souris et non celle du clavier.
    • -maxwarnings nombre
      Définit le nombre maximal d'avertissements à afficher. 0 pour un nombre illimité ; la valeur par défaut est 2 000.
    • -nocrashhandler
      Désactive le gestionnaire de plantage sur les plateformes Unix. Sous Windows, cela réactive la boîte de dialogue « Rapport d’erreurs Windows », qui est désactivée par défaut. Ceci est utile pour le débogage des plantages.
    • -repeat n
      Exécute la suite de tests n fois ou jusqu’à ce qu’un test échoue. Utile pour détecter les tests instables. Si la valeur est négative, les tests sont répétés indéfiniment. Cette option est destinée aux développeurs et n’est prise en charge qu’avec l’enregistreur de journaux en texte brut.
    • -skipblacklisted
      Ignore les tests figurant sur la liste noire. Cette option vise à permettre une mesure plus précise de la couverture des tests en empêchant les tests figurant sur la liste noire de gonfler les statistiques de couverture. Lorsque vous ne mesurez pas la couverture des tests, il est recommandé d’exécuter les tests figurant sur la liste noire afin de détecter tout changement dans leurs résultats, tel qu’un nouveau plantage ou la résolution du problème ayant conduit à leur mise sur liste noire.
    • -platform name
      This command line argument applies to all Qt applications, but might be especially useful in the context of auto-testing. By using the "offscreen" platform plugin (-platform offscreen) it's possible to have tests that use QWidget or QWindow run without showing anything on the screen. Currently the offscreen platform plugin is only fully supported on X11.

    Options d'analyse comparative

    Les options de ligne de commande suivantes permettent de contrôler les tests de performance :

    • -callgrind
      Utilise Callgrind pour chronométrer les tests de performance (Linux et macOS).
    • -perf
      Utilise les événements perf de Linux pour chronométrer les tests de performance
    • -tickcounter
      Utilise les compteurs de ticks du processeur pour chronométrer les tests de performance. Nécessite une prise en charge matérielle.
    • -eventcounter
      Compte les événements reçus pendant les tests de performance.
    • -minimumvalue n
      Définit la valeur minimale acceptable pour la mesure.
    • -minimumtotal n
      Définit le nombre total minimum acceptable pour les exécutions répétées d’une fonction de test.
    • -iterations n
      Définit le nombre d'itérations d'accumulation.
    • -median n
      Définit le nombre d’itérations médianes.
    • -vb
      Affiche des informations détaillées sur les performances.

    Options diverses

    • -help
      Affiche la liste des arguments de ligne de commande possibles et fournit des informations d'aide utiles.

    Qt Test Variables d'environnement

    Vous pouvez définir certaines variables d'environnement afin d'influencer l'exécution d'un autotest :

    • QTEST_DISABLE_CORE_DUMP
      Si vous attribuez à cette variable une valeur différente de zéro, la génération d’un fichier de vidage de mémoire sera désactivée.
    • QTEST_DISABLE_STACK_DUMP
      Définir cette variable sur une valeur non nulle empêchera Qt Test d'afficher une trace de pile en cas de dépassement du délai d'attente ou de plantage d'un autotest.
    • QTEST_FATAL_FAIL
      Définir cette variable sur une valeur non nulle entraînera l'interruption immédiate de l'ensemble de l'autotest en cas d'échec d'un test. Cela s'avère utile, par exemple, pour déboguer une défaillance instable ou intermittente dans un test, en lançant ce dernier dans un débogueur. La prise en charge de cette variable a été ajoutée dans Qt 6.1.

    Création d’un benchmark

    Pour créer un benchmark, suivez les instructions de création d'un test, puis ajoutez la macro ` QBENCHMARK ` ou la fonction ` QTest::setBenchmarkResult()` à la fonction de test que vous souhaitez évaluer. Dans l'extrait de code suivant, c'est la macro qui est utilisée :

    class MyFirstBenchmark: public QObject
    {
        Q_OBJECT
    private slots:
        void myFirstBenchmark()
        {
            QString string1;
            QString string2;
            QBENCHMARK {
                string1.localeAwareCompare(string2);
            }
        }
    };

    Une fonction de test qui mesure les performances doit contenir soit une seule macro ` QBENCHMARK `, soit un seul appel à ` setBenchmarkResult()`. Il est inutile de les répéter plusieurs fois, car un seul résultat de performance peut être rapporté par fonction de test, ou par balise de données dans une configuration pilotée par les données.

    Évitez de modifier le code de test qui constitue (ou influence) le corps d’une macro ` QBENCHMARK `, ou le code de test qui calcule la valeur transmise à ` setBenchmarkResult()`. Idéalement, les différences entre les résultats de performances successifs ne devraient être dues qu’aux modifications apportées au produit que vous testez. Les modifications apportées au code de test peuvent potentiellement entraîner un rapport trompeur concernant un changement de performances. Si vous devez modifier le code de test, indiquez-le clairement dans le message de commit.

    Dans une fonction de test de performances, les appels à ` QBENCHMARK ` ou ` setBenchmarkResult() ` doivent être suivis d’une étape de vérification utilisant ` QCOMPARE()`, ` QVERIFY()`, etc. Vous pouvez alors marquer un résultat de performance comme non valide si un chemin d’exécution différent de celui prévu a été mesuré. Un outil d’analyse des performances peut utiliser ces informations pour filtrer les résultats non valides. Par exemple, une condition d’erreur inattendue entraînera généralement l’interruption prématurée de l’exécution normale du programme, et affichera ainsi à tort une augmentation spectaculaire des performances.

    Sélection du moteur de mesure

    Le code contenu dans la macro QBENCHMARK sera mesuré, et éventuellement répété plusieurs fois afin d’obtenir une mesure précise. Cela dépend du back-end de mesure sélectionné. Plusieurs back-ends sont disponibles. Ils peuvent être sélectionnés sur la ligne de commande (voir Options de benchmark) :

    NomArgument de ligne de commandeDisponibilité
    Temps réel(par défaut)Toutes les plateformes
    Compteur de ticks CPU-tickcounterWindows, macOS, Linux, de nombreux systèmes de type UNIX.
    Compteur d'événements-eventcounterToutes les plateformes
    Valgrind Callgrind-callgrindLinux (si installé)
    Linux Perf-perfLinux

    En résumé, le temps réel est toujours disponible mais nécessite de nombreuses répétitions pour obtenir un résultat exploitable. Les compteurs de ticks sont généralement disponibles et peuvent fournir des résultats avec moins de répétitions, mais peuvent être sensibles aux problèmes de modulation de la fréquence du processeur. Valgrind fournit des résultats exacts, mais ne tient pas compte des temps d’attente d’E/S et n’est disponible que sur un nombre limité de plateformes. Le comptage d’événements est disponible sur toutes les plateformes et fournit le nombre d’événements reçus par la boucle d’événements avant leur envoi vers leurs cibles correspondantes (ce qui peut inclure des événements non-Qt).

    La solution de surveillance des performances sous Linux n’est disponible que sous Linux et fournit de nombreux compteurs différents, qui peuvent être sélectionnés en passant une option supplémentaire « -perfcounter countername », telle que « -perfcounter cache-misses », « -perfcounter branch-misses » ou « -perfcounter l1d-load-misses ». Le compteur par défaut est « cpu-cycles ». La liste complète des compteurs peut être obtenue en exécutant n’importe quel exécutable de benchmark avec l’option « -perfcounterlist ».

    • L'utilisation du compteur de performances peut nécessiter d'activer l'accès aux applications non privilégiées.
    • Les périphériques qui ne prennent pas en charge les temporisateurs haute résolution utilisent par défaut une granularité d'une milliseconde.

    Pour plus d’exemples de tests de performance, consultez la section « Écrire un test de performance » du tutoriel « Qt Test ».

    Utilisation des données de test globales

    Vous pouvez définir une fonction « initTestCase_data() » pour configurer une table de données de test globales. Chaque test est exécuté une fois pour chaque ligne de la table de données de test globale. Lorsque la fonction de test elle-même est pilotée par les données, elle est exécutée pour chaque ligne de données locale, pour chaque ligne de données globale. Ainsi, s’il y a g lignes dans la table de données globale et d lignes dans la table de données propre au test, le nombre d’exécutions de ce test est égal à g fois d.

    Les données globales sont extraites de la table à l’aide de la macro QFETCH_GLOBAL().

    Voici quelques cas d’utilisation typiques des données de test globales :

    • Sélectionner parmi les backends de base de données disponibles dans les tests QSql afin d'exécuter chaque test sur chaque base de données.
    • Effectuer tous les tests réseau avec et sans SSL (HTTP par opposition à HTTPS) et avec ou sans proxy.
    • Tester un minuteur avec une horloge de haute précision et avec une horloge moins précise.
    • Choisir si un analyseur syntaxique doit lire à partir d’un fichier « QByteArray » ou d’un fichier « QIODevice ».

    Par exemple, pour tester chaque nombre fourni par roundTripInt_data() avec chaque locale fournie par initTestCase_data():

    void TestQLocale::roundTripInt()
    {
        QFETCH_GLOBAL(QLocale, locale);
        QFETCH(int, number);
        bool ok;
        QCOMPARE(locale.toInt(locale.toString(number), &ok), number);
        QVERIFY(ok);
    }

    Dans la ligne de commande d’un test, vous pouvez passer le nom d’une fonction (sans préfixe « nom-de-classe-de-test ») pour n’exécuter que les tests de cette fonction. Si la classe de test contient des données globales, ou si la fonction est pilotée par des données, vous pouvez ajouter une balise de données, après deux points, pour n’exécuter que l’ensemble de données correspondant à cette balise pour la fonction. Pour spécifier à la fois une balise globale et une balise spécifique à la fonction de test, combinez-les en les séparant par deux points, en plaçant la balise de données globale en premier. Par exemple

    ./testqlocale roundTripInt:zero

    exécutera le cas de test « zero » du test « roundTripInt() » ci-dessus (en supposant que sa classe « TestQLocale » ait été compilée en un exécutable « testqlocale ») dans chacune des locales spécifiées par « initTestCase_data() », tandis que

    ./testqlocale roundTripInt:C

    exécutera les trois cas de test de roundTripInt() uniquement dans la locale C et

    ./testqlocale roundTripInt:C:zero

    n'exécutera que le cas de test « zero » dans la locale C.

    Disposer d’un contrôle aussi précis sur les tests à exécuter peut considérablement faciliter le débogage d’un problème, car il suffit alors de passer en revue le seul cas de test dont on sait qu’il a échoué.

    © 2026 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.