2010-04-13 22 views
2

Je souhaite tester une requête asynchrone sur un serveur Web. A cette fin, je suis en train de créer simple unittest pour essayer rapidement quelques lignes de code:Qtestlib: QNetworkRequest non exécuté

void AsynchronousCall::testGet() 
{ 
    QNetworkAccessManager *nam = new QNetworkAccessManager(this); 

    QUrl url("http://myownhttpserver.org"); 
    QNetworkRequest req(url); 


    this->connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(reqFinished(QNetworkReply *))); 
    QNetworkReply *rep = nam->get(req); 

} 

void AsynchronousCall::reqFinished(QNetworkReply *rep) 
{ 
    qDebug() << rep->readAll(); 
    qDebug() << "finshed"; 
} 

Le problème est que reqFinished() est jamais atteint. Si j'avais un QEventLoop simple et un loop.exec() juste après le nam-> get (req); la requête est exécutée.

Un conseil? Dois-je utiliser un loop.exec() dans mes unittests?

Répondre

13

Si vous souhaitez tester un comportement asynchrone, vous devez utiliser QEventLoop ou une autre classe avec des fonctionnalités similaires. Je vous suggère d'écrire la méthode aide comme ceci:

bool waitForSignal(QObject *sender, const char *signal, int timeout = 1000) { 
    QEventLoop loop; 
    QTimer timer; 
    timer.setInterval(timeout); 
    timer.setSingleShot(true); 

    loop.connect(sender, signal, SLOT(quit())); 
    loop.connect(&timer, SIGNAL(timeout()), SLOT(quit())); 
    timer.start(); 
    loop.exec(); 

    return timer.isActive(); 
} 

Ensuite, vous pouvez l'utiliser dans vos tests unitaires comme ceci:

void AsynchronousCall::testGet() 
{ 
    QNetworkAccessManager *nam = new QNetworkAccessManager(this); 

    QUrl url("http://myownhttpserver.org"); 
    QNetworkRequest req(url); 


    this->connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(reqFinished(QNetworkReply *))); 
    QNetworkReply *rep = nam->get(req); 
    QVERIFY(waitForSignal(nam, SIGNAL(finished(QNetworkReply*)), 5000)); 
} 

Il y a aussi d'autres problèmes avec votre test:

  1. Les tests qui dépendent de la connexion réseau ne doivent pas être des tests unitaires. Vous voulez que vos tests unitaires soient rapides, ce qui est impossible avec les connexions réseau.
  2. Votre test ne teste pas vraiment quoi que ce soit: il met juste quelques informations pour déboguer la console. Vous devez définir les attentes et les vérifier à l'aide des macros QVERIFY et QCOMPARE.
  3. QTest aspire à mon humble avis. Si vous créez une base de test à partir de zéro, commencez par utiliser gtest + gmock à la place.
+0

Les tests unitaires sont bons pour tester les services de réseau, mais peut se demander si QTest est le moyen de tester quelque chose d'extérieur est la voie à suivre ... – Smar

+1

Il se avère que KDE a une fonction QTest :: kWaitForSignal, qui fait la exactement la même chose. –