IMPORTANT - Synchronize type(), mouseClick(), etc.

Last edited on

A problematic Example

The type() command (as well as other commands) sends key or mouse events to the application. For example:

import names

def main():
    startApplication("my_application")
    #...

    type(waitForObject(names.Article_Name_TextField), "My new article x")
    test.compare(waitForObject(names.Error_Label).text, "This article already exists!")
test.py

This test script implies that there is a TextField object for entering a new article's name, and that there is a Label object that shows an error message in case the entered article name already exists.

However, there is a potential problem with this script:

Because it is in general not possible to know when an application has received or has finished processing key events, Squish has no other choice but to execute the next command (test.compare()) right away.

However, this could result in the text value being read from the TextField before all key events have been processed (for example the TextField might contain only "My new art" at that time). That in turn could result in the test.compare() to fail, because that expects the TextField to contain "My new article x" for the error message "This article already exists!" to be shown in the Label object.

Solution #1 - Pause script to ensure events have been processed

One solution could be to snooze() the test script for a fixed time that is large enough to ensure that the key events have been processed:

import names

def main():
    startApplication("my_application")
    #...

    type(waitForObject(names.Article_Name_TextField), "My new article x")

    # Synchronize:
    # Is 0.5 seconds really long enough, even on our slow
    # nightly test machines?
    snooze(0.5)

    test.compare(waitForObject(names.Error_Label).text, "This article already exists!")
test.py

Solution #2 - Wait for desired condition first, then proceed

import names 

def main():
    startApplication("my_application")
    #...

    type(waitForObject(names.Article_Name_TextField), "My new article x")

    # Synchronize:
    for _ in range(5):
        if waitForObject(names.Error_Label).text == "My new article x":
            break
        snooze(1.0)
    else:
        test.fail("Sync failed for textfield after 5 seconds")

    test.compare(waitForObject(names.Error_Label).text, "This article already exists!")
test.py

Another possibly problematic Example

Here is another example, this time with a TextField and a Button object (Add Article) for adding a "new article":

import names 

def main():
    startApplication("my_application")
    #...

    type(waitForObject(names.Article_Name_TextField"), "My new article x")
    clickButton(waitForObject(names.Add_Article"))
test.py

Here the key event processing may still be going on in the application while Squish already clicks the Add Article button. So this could result in an article to be added with a "truncated" title.

For this the same additional synchronization like in the first example can be applied.