如何使用QtTest测试带自定义模型与委托的QTableView?
Qt MVC委托(Combobox/Spinbox)GUI测试实现方案
问题根因
你遇到的多按下箭头不生效的核心原因有两个:
- 模拟事件时没有等待Qt事件循环完成界面状态更新,后续按键事件被未激活的控件拦截
- 按键事件没有发送到Combobox下拉列表的实际接收控件,而是发给了QTableView或者Combobox本体,只有第一次按键刚好触发下拉框弹出,后续事件无法命中目标
通用测试前置规则
- 所有模拟操作后必须加20~50ms的
QTest::qWait等待,保证界面状态同步完成 - 必须通过
QTableView::indexWidget()拿到对应单元格动态生成的编辑器实例,所有事件直接发送给该实例,不要全局发送给视图
Combobox委托测试代码示例
// 假设测试第0行第0列的单元格 QModelIndex testIndex = customModel->index(0, 0); // 1. 双击唤出编辑器,等待渲染完成 QTest::mouseDClick(tableView->viewport(), Qt::LeftButton, {}, tableView->visualRect(testIndex).center()); QTest::qWait(30); // 2. 拿到实际生成的Combobox编辑器实例 QComboBox* editor = qobject_cast<QComboBox*>(tableView->indexWidget(testIndex)); Q_ASSERT(editor != nullptr); // 3. 主动弹出下拉列表,等待下拉控件初始化完成 editor->showPopup(); QTest::qWait(30); // 4. 给下拉列表控件发送按键事件,不要发给Combobox本体 QAbstractItemView* popupView = editor->view(); // 选中第3个选项(从默认选中第0个到第2个索引需要按2次下箭头) for(int i=0; i<2; i++){ QTest::keyClick(popupView, Qt::Key_Down); QTest::qWait(10); } // 5. 按回车确认选择 QTest::keyClick(popupView, Qt::Key_Enter); QTest::qWait(30); // 6. 校验模型存储值是否符合预期 QCOMPARE(customModel->data(testIndex, Qt::UserRole).toInt(), 你期望的UserRole数值); QCOMPARE(customModel->data(testIndex, Qt::DisplayRole).toString(), 你期望的显示文本);
Spinbox委托测试代码示例
// 假设测试第0行第1列的单元格 QModelIndex testIndex = customModel->index(0, 1); // 1. 单击唤出Spinbox编辑器 QTest::mouseClick(tableView->viewport(), Qt::LeftButton, {}, tableView->visualRect(testIndex).center()); QTest::qWait(30); // 2. 拿到Spinbox实例 QSpinBox* editor = qobject_cast<QSpinBox*>(tableView->indexWidget(testIndex)); Q_ASSERT(editor != nullptr); // 常规值测试方案 editor->clear(); QTest::keyClicks(editor, "25"); // 模拟输入25 QTest::keyClick(editor, Qt::Key_Enter); QTest::qWait(30); QCOMPARE(customModel->data(testIndex, Qt::DisplayRole).toInt(), 25); // 边界值测试方案(适合快速校验范围限制逻辑) editor->setValue(100); // 假设Spinbox限制范围是0~99 Q_EMIT editor->editingFinished(); QTest::qWait(30); QCOMPARE(customModel->data(testIndex, Qt::DisplayRole).toInt(), 99);
常见避坑点
- 如果你的委托重写了
editorEvent、setEditorData、setModelData方法,优先单独做单元测试校验逻辑正确性,再做GUI集成测试 - 不要省略
QTest::qWait,Qt的GUI渲染、事件传递都是异步逻辑,无等待状态下发送的事件大概率会被丢弃 - 如果测试时需要主动关闭编辑器提交数据,可以调用
tableView->closePersistentEditor(testIndex)触发委托的setModelData逻辑
内容的提问来源于stack exchange,提问作者Ulrich Von Rekkenin
相关产品推荐
相关产品推荐

