使用Qt Test测试模态对话框

时间:2012-03-01 15:01:14

标签: unit-testing qt modal-dialog

我正在尝试使用QTestLib为GUI应用程序编写单元测试。问题是其中一个插槽使用exec()创建了一个模态对话框,我发现没有可能与对话框进行交互。

创建对话框的插槽连接到QAction。所以第一个问题是当我在测试中触发QAction时测试阻塞,因为这会导致调用exec()。因此,我尝试创建一个执行交互的QThread。但是,这没有用。

我已经尝试过的事情(都是在“交互助手”线程中执行的):

  1. 使用QTest::keyClicks()发送关键点击次数
    • 导致错误消息“QCoreApplication :: sendEvent():无法将事件发送到不同线程拥有的对象”
  2. 使用QCoreApplication::postEvent()发布QKeyEvents
    • 不起作用,即没有任何反应。我猜是因为事件最终出现在拥有对话框的线程的事件循环中,直到对话框关闭并且exec()返回时才会到达。 请参阅下面的编辑
  3. 使用QMetaObject::invokeMethod()在对话框中调用插槽
    • 不起作用,即没有任何反应。我想因为postEvent()不起作用的原因相同。 请参阅下面的编辑
  4. 所以问题是:有没有办法以编程方式与使用exec()方法打开的模态对话框进行交互?

    编辑:实际上,方法3正在运行。问题是另一个问题: 我将参数传递给invokeMethod()到“交互助手”线程,由于某种原因,访问参数不起作用(我没有SEG错误,但它们只是空的)。 我想方法2也有效,我只是遇到与方法3相同的问题,但我没有测试过。

4 个答案:

答案 0 :(得分:6)

我在命令行应用程序中使用的解决方案使用了用于GUI的Qt库,singleShotthis answer暗示。在这些情况下,它看起来像这样:

QCoreApplication app(argc, argv);

// ...

QTimer::singleShot(0, &app, SLOT(quit()));
return app.exec();

所以在你的情况下,我想它看起来像这样:

QDialog * p_modalDialog = getThePointer(); // you will have to replace this with
                                           // a real way of getting the pointer

QTimer::singleShot(0, p_modalDialog, SLOT(accept()));

p_modalDialog->exec(); // called somewhere else in your case
                       // but it will be automatically accepted.

答案 1 :(得分:3)

通过延迟执行直到对话框事件循环开始,您可以将交互保持在同一个线程中。

例如,在exec()调用之前,您使用QTimer::singleShot为0作为间隔,或QMetaObject::invokeMethod使用连接类型Qt::QueuedConnection来调用需要执行的插槽显示对话框时。

答案 2 :(得分:2)

您还可以在致电exec()之前发布活动。 一旦在exec()调用之后构建了对话框,就会执行事件。

例如,要测试Esc键按下(表示拒绝/关闭对话框):

// create a dialog
QDialog d = ...
//post an Escape key press and release event
QApplication::postEvent(&d, new QKeyEvent(QEvent::KeyPress  , Qt::Key_Escape, Qt::NoModifier) );
QApplication::postEvent(&d, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Escape, Qt::NoModifier) );
// execute and check result
int ret = d.exec();
QCOMPARE(ret, static_cast<int>(QDialog::Rejected));

答案 3 :(得分:0)

相关问题的答案有一些关于在测试期间刷新事件队列的额外细节: Qt event loop and unit testing?