我正在尝试使用QTestLib为GUI应用程序编写单元测试。问题是其中一个插槽使用exec()
创建了一个模态对话框,我发现没有可能与对话框进行交互。
创建对话框的插槽连接到QAction。所以第一个问题是当我在测试中触发QAction时测试阻塞,因为这会导致调用exec()
。因此,我尝试创建一个执行交互的QThread。但是,这没有用。
我已经尝试过的事情(都是在“交互助手”线程中执行的):
QTest::keyClicks()
发送关键点击次数
QCoreApplication::postEvent()
发布QKeyEvents
exec()
返回时才会到达。QMetaObject::invokeMethod()
在对话框中调用插槽
postEvent()
不起作用的原因相同。所以问题是:有没有办法以编程方式与使用exec()
方法打开的模态对话框进行交互?
编辑:实际上,方法3正在运行。问题是另一个问题:
我将参数传递给invokeMethod()
到“交互助手”线程,由于某种原因,访问参数不起作用(我没有SEG错误,但它们只是空的)。
我想方法2也有效,我只是遇到与方法3相同的问题,但我没有测试过。
答案 0 :(得分:6)
我在命令行应用程序中使用的解决方案使用了用于GUI的Qt库,singleShot
,this 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?