[Qt-qml] Find by id.
michael.brasser at nokia.com
michael.brasser at nokia.com
Thu Nov 11 02:07:20 CET 2010
Hi,
On 05/11/2010, at 9:21 PM, ext René Hansen wrote:
> On Thu, 2010-11-04 at 23:44 +0100, Brasser Michael
> (Nokia-MS-Qt/Brisbane) wrote:
>> On 04/11/2010, at 10:26 PM, ext René Hansen wrote:
>>> I'd like to be able to find child objects in a QML structure and to do
>>> that, I've exposed a new QML Object with qmlRegisterType, which provides
>>> me with:
>>>
>>> QObject *QmlUnitTestHelper::getChildById(QObject *parent, QString name) {
>>> return parent->findChild<QObject *>(name);
>>> }
>>>
>>> And in Qml I have something like this:
>>>
>>> Rectangle {
>>>
>>> QmlUnitTestHelper {
>>> id: quth
>>> }
>>>
>>> Rectangle {
>>> id:outerRect
>>> Rectangle {
>>> id:innerRect
>>> Text {
>>> id:label
>>> text: "Hello World"
>>> }
>>> }
>>> }
>>> }
>>>
>>> Which should enable me to test in something like this manner:
>>>
>>> quth.getChildById(outerRect, "innerRect").label.text == "Hello World"
>>>
>>> However, this doesn't work as expected, so I guess my assuming the QML
>>> id property being the same as a QObjects objectName is faulty.
>>
>> That's correct -- id and objectName are separate. You can explicitly give a QML item an objectName, though, if needed:
>>
>> Rectangle {
>> id: myRect
>> objectName: "theRectangle"
>> }
>>
>> (Bea has just added some great documentation on this, which should hopefully be showing up on the website soon)
>>
>>> How would I go about doing something like this?
>>
>> For the above example, you should be able to test the label's text with:
>> label.text == "Hello World"
>> (within a component, the id space is "flat", rather than qualified)
>>
>> If you need to access the item from outside the component, a property alias (http://doc.qt.nokia.com/4.7/qml-extending-types.html#property-aliases) might help. You could for example add
>>
>> property alias testLabel: label
>>
>> to the top-most Rectangle to make label accessible to the "outside world" via testLabel.
>
> This is what I'd like to avoid though. It would be preferable not to
> have to clutter up the codebase, just to be able to test it.
>
>>
>> From the class name, it looks like you might be looking at writing autotests in QML? If so (and If you haven't seen them already), here are a few projects that might be of interest:
>> * qmlunit (https://github.com/fgrehm/qmlunit)
>> * the Qt3D team's QML unit testing (http://qt.gitorious.org/qt-labs/qt3d/trees/master/tests/auto/qml3d)
>
> It is for autotesting yes and I have based it on qmlunit. With qmlunit
> there is some shortcomings though, so I've had to remodel it a bit.
> Basically with qmlunit, you load the QML object that you want to test in
> another qml object, a QmlTestCase, and interact with it from there. So
> let's say I want to test the object that is my whole application. E.g.
> Main { id: main }, I've left out child elements, but imagine I have a
> lot of stuff, buttons etc. several states even.
>
> Then I would like to test application logic by sending keypresses and
> mouseclicks on certain child elements of my application, buttons, inputs
> etc.
Another thing you might be interesting in looking at is the visual test infrastructure (note that it's experimental, there are no compatibility guarantees, etc), located in tests/auto/declarative/qmlvisual. It handles interaction by sending events to the scene as a whole (with e.g. the global position information for a mouse event) and letting the scene send the event to the appropriate element.
> However, since I've instantiated my application in another qml file, the
> internal id's of main are not accessible, so how do I send a click event
> to a button for instance?
>
> That was why I wanted to have a getChildById method, so I could actually
> find the element I wanted and send it whatever event.
>
> The way I've done it now is to enforce setting objectName on all
> elements that I need to access to and then instead of having
> getChildById, it's getChildByObjectName, which is just
> QObject::findChild() wrapped.
>
> My point is that identical id and objectName makes for redundant code,
> so if there was a way of addressing by id, as done in QML, it would
> definitely help quell my OCD and make for a more DRY feel of the QML
> code.
I agree having to add objectName (or lots of property aliases) to production code simply for testing is not an ideal solution. I'm hesitant about a getChildById() for general QML programming, but it seems to make sense in an auto testing (and accessibility?) context, so maybe we should look for specific solutions there first (addressing e.g. the issues that Alan raised in another thread).
Regards,
Michael
More information about the Qt-qml
mailing list