你如何在QTest单元测试中编辑QTableView单元格?

12

我正在使用QTestLib框架编写自定义验证器在QTableView上的单元测试。其中最基本的测试用例如下:

双击第三列和第四行的表格单元格,并将数字“5”附加到其内容中。

简单地更改模型中的值或其他任何内容是不够的,测试用例应该像这样执行:

  1. 双击表格单元格以将其设置为编辑模式
  2. 按[End]键。
  3. 按[5]键。

注意:此问题有一个关于如何从代码中将表格单元格设置为编辑模式的答案,但单元测试应尝试遵循人类用户的可能性,即鼠标/键盘操作。

我发现可以使用QTableView::columnViewportPosition(int)QTableView::rowViewportPosition(int)来检索单元格的X/Y位置。然而,使用QTest::mouseDClick(...)在指定的位置上双击既不选择单元格,也不将其设置为编辑模式:

// Retrieve X/Y coordinates of the cell in the third column and the fourth row
int xPos = m_pTableView->columnViewportPosition( 2 );
int yPos = m_pTableView->rowViewportPosition( 3 );

// This does not work
QTest::mouseDClick( m_pTableView, Qt::LeftButton, QPoint( xPos, yPos ) );

我如何仅使用鼠标/键盘操作来实现我上面描述的测试用例?

PS:我正在尝试在Windows XP 32位和Qt 4.6.1下进行此操作。

1个回答

14

在尝试通过模拟事件在 QTableView 中进行编辑时,需要考虑几个问题:

QTableView 不直接显示其单元格,而是使用其 viewport() 进行显示。同样,双击事件必须发送到视口而不是表格视图本身。

现在当你执行以下操作时:

QTest::mouseDClick( m_pTableView->viewport(), Qt::LeftButton, 
                    NULL, QPoint( xPos, yPos ) );

这个单元格将会被选中,但不处于编辑模式(与人工双击不同,即使tableView没有聚焦在该单元格上也能立即触发编辑模式)。但如果您在双击之前在同一位置进行单击,则会起作用!

如果您随后发送[End]键按事件到视口,光标将不会跳转到表格单元格内容的结尾,而是选择当前行中的最后一个单元格。
要更改表格单元格内容,必须将事件发送给当前的编辑器小部件。最简单的方法是使用QWidget::focusWidget()

QTest::keyClick( m_pTableView->viewport()->focusWidget(), Qt::Key_End );

需要注意的是,这种使用方式可能不安全,因为focusWidget()可能返回NULL。


有了这个知识,测试用例可以按如下编写:

// Note: The table view must be visible at this point

// Retrieve X/Y coordinates of the cell in the third column and the fourth row
int xPos = m_pTableView->columnViewportPosition( 2 ) + 5;
int yPos = m_pTableView->rowViewportPosition( 3 ) + 10;

// Retrieve the viewport of the table view
QWidget* pViewport = m_pTableView->viewport();

// Double click the table cell to set it into editor mode
// Note: A simple double click did not work, Click->Double Click works, however
QTest::mouseClick ( pViewport, Qt::LeftButton, NULL, QPoint( xPos, yPos ) );
QTest::mouseDClick( pViewport, Qt::LeftButton, NULL, QPoint( xPos, yPos ) );

// Simulate [End] keypress
QTest::keyClick( pViewport->focusWidget(), Qt::Key_End );

// Simulate [5] keypress
QTest::keyClick( pViewport->focusWidget(), Qt::Key_5 );

(注意:如果您想要验证此内容,您可以在每个事件后添加QTest::qWait( 1000 )命令)


如果您按照此处所述使用_data()函数,请注意在数据创建时无法检索focusWidget()。 我通过创建一个只有纯虚拟"execute()"函数的自定义接口ITestAction来解决了这个问题。然后,我添加了类似于QTest::mouseClick(...)等函数的构造函数的子类。这些类只是调用QTest函数,但根据附加的布尔标志使用小部件本身或其焦点小部件作为参数。 然后,_data()插槽为每个数据行存储一个QList< ITestAction* >列表,而实际测试插槽则遍历该列表并在执行验证之前在每个项上调用execute()。


这正是我需要的答案,非常感谢 :) - astrojuanlu
在以下代码中,+5和+10是什么意思: int xPos = m_pTableView->columnViewportPosition( 2 ) + 5; int yPos = m_pTableView->rowViewportPosition( 3 ) + 10; - NiladriBose
2
@NiladriBose:这些是像素数。由于我们正在模拟点击,我们可能希望在单元格内部的某个位置进行点击,而不是在其边框上,以确保选择正确的单元格。 - Michał Góral
除了使用x-y坐标选择单元格之外,你还可以使用edit槽。使用view->edit(index) - Woltan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接