繁体   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