Qt 自动 UI 测试因消息框而停止.如何在消息框中模拟输入?



我的任务是为正在开发的软件编写一个自动化的UI测试。碰巧,有单选按钮触发一个消息框,它会停止我的自动测试,直到我手动确认它(按 ENTER)。问题是我不知道如何调用新调用的消息框,然后由QTest::keyClick(<object>, QtKey::Key_Enter);确认并让我的自动测试继续运行。

我正在使用QWidgets,QApplication,Q_OBJECT和QtTest。 我将提供一个类似于我正在使用的代码:

void testui1(){
Form1* myform = new Form1();
myform->show();
QTest::mouseClick(myform->radioButton01, Qt::LeftButton, Qt::NoModifier, QPoint(), 100);
// Message box pops up and stops the operation until confirmed
QTest::mouseClick(myform->radioButton02, Qt::LeftButton, Qt::NoModifier, QPoint(), 100);
// again
...
}

如何编写脚本以自动确认消息框?消息框只是一个 [OK] 类型,因此无论我按了"是"还是"否",我都不需要它返回。QTest::keyClick(<target object>, Qt::Key_Enter)方法需要知道它应该按回车键到哪个对象。我尝试将myform包含在对象中,但它不起作用。谷歌搜索我没有找到答案。我发现以下结果不适用于我正在寻找的内容

QWidgetList allToplevelWidgets = QApplication::topLevelWidgets();
foreach (QWidget *w, allToplevelWidgets) {
if (w->inherits("QMessageBox")) {
QMessageBox *mb = qobject_cast<QMessageBox *>(w);
QTest::keyClick(mb, Qt::Key_Enter);
}
}

问题是,一旦你"点击"了单选按钮,这会导致QMessageBox::exec被调用,你的代码就会停止运行,直到用户点击按钮。

您可以通过在单击单选按钮之前启动计时器来模拟用户单击按钮。

在计时器的回调函数中,可以使用QApplication::activeModalWidget()获取指向消息框的指针,然后只需对其调用close

QTimer::singleShot(0, [=]()
{
QWidget* widget = QApplication::activeModalWidget();
if (widget)
widget->close();
});

如果要按消息框上的特定键,可以使用QCoreApplication::postEvent将键事件发布到消息框

QTimer::singleShot(0, [=]()
{
int key = Qt::Key_Enter; // or whatever key you want
QWidget* widget = QApplication::activeModalWidget();
if (widget)
{
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); 
QCoreApplication::postEvent(widget, event);
}
});

因此,就这如何与您给出的示例代码相关联而言:

void testui1()
{
Form1* myform = new Form1();
myform->show();
QTimer::singleShot(0, [=]()
{
QWidget* widget = QApplication::activeModalWidget();
if (widget)
widget->close();
else
QFAIL("no modal widget");
});
QTest::mouseClick(myform->radioButton01, Qt::LeftButton, Qt::NoModifier, QPoint(), 100);
}

将上述所有内容组合在一起的示例应用:

#include <QApplication>
#include <QMainWindow>
#include <QHBoxLayout>
#include <QPushButton>
#include <QTimer>
#include <QMessageBox>
#include <iostream>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QMainWindow window;
QWidget widget;
window.setCentralWidget(&widget);
QHBoxLayout layout(&widget);
QPushButton btn("go");
layout.addWidget(&btn);
QObject::connect(&btn, &QPushButton::clicked, [&]()
{
QTimer::singleShot(0, [=]()
{
QWidget* widget = QApplication::activeModalWidget();
if (widget)
{
widget->close();
}
else
{
std::cout << "no active modaln";
}
});
QMessageBox(
QMessageBox::Icon::Warning,
"Are you sure?",
"Are you sure?",
QMessageBox::Yes | QMessageBox::No,
&window).exec();
});
window.show();
return app.exec();
}

单击Go看起来什么都没发生,因为QMessageBox会立即关闭。

若要证明消息框显示然后关闭,可以增加调用中QTimer::singleShot的时间,例如1000。现在它将显示消息框 1 秒,然后由计时器关闭。

最新更新