PDA

View Full Version : unit test focus behavior with QTest



bob_smith
17th November 2010, 01:02
Hi

I’ve just switched to Qt and have created a new widget derived from QLineEdit that I am trying to unit test. So far I’ve been able to test everything except some custom behavior on gain/lose focus. Basically the text of the control (potentially) changes when it gains/loses focus and I would like to test this behavior. I can’t find anything in QTest, the qtestlib tutorial, or searching this forum (I accept that my searching ability may be lacking but I tried most combinations of qtest, unit test, qtestlib, simulate, and focus) and am hoping someone can at least point me in the right direction or let me know if it isn't possible.

In short, I want a test that does the following:



//inside a test
my_ctrl ctrl;

QTest::keyClicks(&ctrl, "1.23456789");

//how do I cause ctrl to think it has lost focus here?

QString desired_result = //desired result, something other than “1.23456789”

QCOMPARE(ctrl.text(), desired_result);


Thank you for your help

MarekR22
17th November 2010, 14:36
Why you don't just call QWidget API: QWidget::setFocus and QWidget::clearFocus?

bob_smith
17th November 2010, 18:06
Tried clearFocus but that didn't work. According to the docs



If the widget has active focus, a focus out event is sent to this widget to tell it that it is about to lose the focus.


Maybe "about to lose focus" is different from actually losing focus? I don't see how I can check setFocus without having a way to remove focus

For the record, I've tested my control in a test app to make sure it actually works, which it does. All I wish to do now is enshrine this behavior in a unit test.

Here's a more complete yet still simple example of what I'm after:

my_ctrl header


class my_ctrl : public QLineEdit
{
Q_OBJECT

public:
my_ctrl(QWidget * parent = 0);
~my_ctrl();

protected:
virtual void focusInEvent(QFocusEvent * e);
virtual void focusOutEvent(QFocusEvent * e);
};


my_ctrl implementation


my_ctrl::my_ctrl(QWidget * parent)
: QLineEdit(parent)
{}

my_ctrl::~my_ctrl()
{}


void my_ctrl::focusInEvent(QFocusEvent * e)
{
setText("Focus In");
QLineEdit::focusInEvent(e);
}

void my_ctrl::focusOutEvent(QFocusEvent * e)
{
setText("Focus Out");
QLineEdit::focusOutEvent(e);
}


test code


class test_my_ctrl : public QObject
{
Q_OBJECT
private slots:
void test_lose_focus();
};



void test_my_ctrl::test_lose_focus()
{
my_ctrl ctrl;

QTest::keyClicks(&ctrl, "1.23456789");

QCOMPARE(ctrl.text(), QString("1.23456789"));

ctrl.clearFocus(); //doesn't work

QCOMPARE(ctrl.text(), QString("Focus Out")); //fails with Actual (ctrl.text()): 1.23456789

}


QTEST_MAIN(test_my_ctrl)
#include "main.moc"

MarekR22
17th November 2010, 19:57
This should look like this (simple version):

void test_my_ctrl::test_lose_focus()
{
my_ctrl ctrl;
ctrl.setFocus(Qt::TabFocusReason); // first you make sure that focus is in correct place
ctrl.selectAll(); // just in case if it is not selected, so old content will be replaced
QTest::keyClicks(&ctrl, "1.23456789", Qt::NoModifier, 10); // then you type

QCOMPARE(ctrl.text(), QString("1.23456789"));
ctrl.clearFocus();
QTest::qWait(100); // this may be needed to process some of posted events - it may be not needed
QCOMPARE(ctrl.text(), QString("Focus Out"));
}
Focus in event should be done in similar manner.
Advanced version should be data driven.

bob_smith
17th November 2010, 20:46
Nope, gave it up to a second (QTest::qWait(1000)) and still no good. Did you actually try your suggestion and, if so, using what platform and version? I ask because I went through a long conversation about a problem in wxWidgets (the framework that I'm moving from) that ended up being just a difference in event propagation behavior on different platforms.

MarekR22
17th November 2010, 21:38
We both forgot about little detail. To have focus widget HAS TO BE VISIBLE and I'm sure that this is the problem.
So just add ctrl.show() on front (or give parent which is visible) :).

bob_smith
17th November 2010, 22:22
Sure enough that works. The only downside is that now the control is visible when the tests are run, of course. Originally I was hoping to have something that works in the same way as QTest::keyClicks in that the control is never actually visible to whoever is running the test when the keystrokes are entered. However now at least I have something that works, I’ll just have to see if it acceptable for use in our build process.

Thank you for your help.

yunuscanemre
19th August 2015, 20:21
Sure enough that works. The only downside is that now the control is visible when the tests are run, of course. Originally I was hoping to have something that works in the same way as QTest::keyClicks in that the control is never actually visible to whoever is running the test when the keystrokes are entered. However now at least I have something that works, I’ll just have to see if it acceptable for use in our build process.

Thank you for your help.

I know this is an old thread but I am posting this in case anyone else comes across it. I was able to get the focus events working during tests without having to show the widget. I called "QApplication::setActiveWindow(patient_);", where patient is my main widget which holds other widgets in it like line edits etc. After this focus events propagated properply.