How can you edit a QTableView cell from a QTest unit test?

I am writing a unit test for a custom validator in a QTableView using the QTestLib framework . One of the simplest test cases can be described as follows:

Double-click the table cell in the third column and fourth row and add the number "5" in its contents.

It is not enough just to change the value in the model or something else, the test case should do it as follows:

  • Double-click a table cell to set it to edit mode.
  • Press the [End] key.
  • Press the [5] key.

Note: This question answers the question of how to set a table cell to edit mode from code, however unit test should try to adhere to user-user capabilities, i.e. mouse / keyboard actions.

I found out that the X / Y position of the cell can be restored using QTableView :: columnViewportPosition (int) and QTableView :: rowViewportPosition (int) . However, double-clicking at the specified location with QTest :: mouseDClick (...) does not select the cell and does not set it to edit mode:

// 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 ) ); 

How can I implement the test scenario that I described above using only mouse / keyboard actions?

PS: I'm trying to do this under Windows XP 32 bit and Qt 4.6.1

+6
source share
1 answer

When trying to edit in QTableView using simulated events, there are a few things to consider:

QTableView does not display its cells directly; it does this with viewport () . Similarly, a double-click event should be sent to the viewer instead of the table view itself.

Now when you do

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

the cell will be selected, but not in edit mode (unlike the double-click initiated by a person who instantly puts the cell in edit mode, even if there was no focus in the table view before). However, if you add one click to the same place before double-clicking, it will work!

If you then sent [End] to the viewport, the cursor would not have moved to the end of the contents of the table cell, but instead select the last cell in the current row.
To change the contents of a table cell, you must send this event to the current editor widget. The easiest way to do this is to use QWidget :: focusWidget ()

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

Note that using this type may be unsafe, although since focusWidget () may return NULL.


With this knowledge, the test case can be programmed as follows:

 // 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 ); 

(Note: if you want to verify this, you can add the QTest :: qWait (1000) commands after each event)


If you use the _data () functions, as described here , note that you cannot get focusWidget () while creating the data, I solved this problem by creating my own ITestAction interface ITestAction only a clean virtual execute () function. Then I added subclasses with a similar constructor, like the QTest::mouseClick(...) etc functions. These classes simply call the QTest functions, but use either the widget itself or the focus widget as a parameter, depending on the additional Boolean flag. The _data () slot then stores a QList <ITestAction *> for each row of data, and the actual test slot iterates over this list and calls execute () for each element before performing the check.

+5
source

Source: https://habr.com/ru/post/926321/


All Articles