2

Webサーバーへの非同期リクエストをテストしたいと思います。そのために、数行のコードをすばやく試すための簡単な単体テストを作成しています。

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

問題は、reqFinished()に到達しないことです。単純なQEventLoopと、nam-> get(req);の直後にloop.exec()がある場合。リクエストが実行されます。

ヒントはありますか?すべてのユニットテストでloop.exec()を使用する必要がありますか?

4

1 に答える 1

13

非同期動作をテストする場合は、QEventLoopまたは同様の機能を持つ他のクラスを使用する必要があります。次のようなヘルパーメソッドを作成することをお勧めします。

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();
}

次に、次のように単体テストで使用できます。

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

テストには他にも問題があります。

  1. ネットワーク接続に依存するテストは、単体テストであってはなりません。ユニットテストを非常に高速にする必要があります。これは、ネットワーク接続では実現できません。
  2. あなたのテストは実際には何もテストしません:それはただデバッグコンソールにいくつかの情報を置くだけです。期待値を定義し、QVERIFYおよびQCOMPAREマクロを使用してそれらを検証する必要があります。
  3. QTestは私見を吸います。テストベースを最初から作成する場合は、代わりにgtest + gmockの使用を開始してください。
于 2010-04-13T14:02:40.170 に答える