簡體   English   中英

如何在GoogleTest中使用QTimers

[英]How to use QTimers in GoogleTest

我在單元測試期間遇到一些情況,我希望某些QTimer的超時在某個QObject中觸發一些插槽。 如何做到這一點以及此測試的一些常見缺陷並不是很明顯。

這種模式是我發現的作品。 我懷疑它可能在某種程度上依賴於線程模型,因此我提供了一個YMMV的小注釋。

假設你有一些

class Foo : public QObject{
  ...
  public:
  QTimer* _timer;

  public slots:
  virtual void onTimeout();
  ...
}

為簡單起見,讓我們假裝這是一個私有實現類,這就是暴露計時器的原因,而插槽是虛擬的,所以我們可以模擬它。

class MockFoo : public Foo{
public:
  MOCK_METHOD0(onTimeout, void());
}

首先,當使用Qt中的QTimers和其他線程模型時,我們必須修改google test的'main'功能:

int main(int argc, char **argv) {
    QCoreApplication app(argc, argv);

    ::testing::InitGoogleTest(&argc, argv);
    int ret = RUN_ALL_TESTS();

    QTimer exitTimer;
    QObject::connect(&exitTimer, &QTimer::timeout, &app, QCoreApplication::quit);
    exitTimer.start();
    app.exec();
    return ret;
}

接下來,在測試套件中:

TEST_F(Foo_Tests, onTimeout){
  MockFoo* foo{new MockFoo};
  //using Qt 5 convention, but do what you gotta do for signal spy in your setup
  QSignalSpy timeoutSpy(foo->_timer, &QTimer::timeout);
  QSignalSpy deleteSpy(foo, &QObject::destroyed);

  foo->_timer->setInterval(0);
  foo->_timer->setSingleShot(true);

  EXPECT_CALL(*foo, onTimeout());

  foo->_timer->start();

  EXPECT_TRUE(timeoutSpy.wait(100));
  foo->deleteLater();
  deleteSpy.wait(100);
}

關於這一點的一些注意事項非常重要

  1. 即使你已經在測試套件中的其他地方有一個MockFoo,你需要在這一個測試中創建和銷毀一個。 我懷疑這與QTimer和Qt的線程模型/事件循環有關。
  2. 假設你在別處做了類似的測試,它可能是一個不同的類,不同的套件,不同的命名空間,一切。 如果您的EXPECT_CALL在此處未飽和(或其他一些谷歌測試測試),使用此模式的下一個測試將失敗,但它會抱怨此測試的預期。
    • 例如:Bar_test失敗:MockFoo :: onTimeout預計會被調用一次,實際上不被稱為notisfied和active
  3. 在退出之前等待對象被銷毀是很重要的。 這允許Qt事件循環處理此對象上的掛起操作,即觸發插槽的超時信號。
  4. 即使真正的程序使用非SingleShot計時器,在這里設置它也會簡化它,以便不會多次調用插槽,從而擾亂測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM