如何从QTest单元测试中编辑QTableView单元?

Tim*_*yer 6 qt qt4 qtableview qtestlib qt4.6

我正在使用QTestLib框架在QTableView中为自定义Validator编写单元测试.最基本的测试用例之一可以这样描述:

双击第三列和第四行中的表格单元格,并在其内容中附加数字"5".

仅仅改变模型中的值或任何东西是不够的,测试用例应该像这样执行:

  1. 双击表格单元格将其设置为编辑模式
  2. 按[结束]键.
  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 ) );
Run Code Online (Sandbox Code Playgroud)

如何使用鼠标/键盘操作实现上述测试用例?

PS:我在Windows XP 32位和Qt 4.6.1下尝试这个

Tim*_*yer 7

尝试通过模拟事件在QTableView中进行编辑时,需要考虑以下几点:

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

现在当你这样做

QTest::mouseDClick( m_pTableView->viewport(), Qt::LeftButton, 
                    NULL, QPoint( xPos, yPos ) );
Run Code Online (Sandbox Code Playgroud)

细胞将被选中,而不是在编辑模式(不同于人类发起双击它立即使细胞进入编辑模式即使表视图以前没有焦点).但是,如果您在双击之前在同一位置添加单击,则它将起作用!

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

QTest::keyClick( m_pTableView->viewport()->focusWidget(), Qt::Key_End );
Run Code Online (Sandbox Code Playgroud)

请注意,使用它可能是不安全的,因为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 );
Run Code Online (Sandbox Code Playgroud)

(注意:如果要验证这一点,可以在每个事件后添加QTest :: qWait(1000)命令)


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

  • @NiladriBose:这些是像素数。当我们模拟点击时,我们可能想要点击单元格内部的某个位置,而不是其边框,只是为了确保选择正确的单元格。 (2认同)