How to Create and Use Synchronization Points
When recording a script in Squish, the event recorder must ensure that the AUT and the test script are synchronized. One way of achieving this is for the recorder to automatically insert snooze(seconds) statements into the script. From Preferences - Squish - Recording - Script Synchronization, you can select Based on Time During Recording to get this behavior.
snooze() statements force the script to wait for a specified number of seconds (which might be a fractional amount such as 2.5). Time-Based Synchronization attempts to ensure that a script is replayed at roughly the same speed as it was recorded. For example, if the user waited for a window to pop up, the script will wait for the same amount of time. This makes playback slow enough to be followed by the human eye.
Note: There is a 45-minute Online course about Test Synchronization in Squish at the
if you desire some video guidance.
Using snooze(seconds) statements is the simplest way to synchronize the AUT and a test script. But in many cases, simply waiting for a certain amount of time isn't sufficient. For example, if a script is recorded on a fast machine and later replayed on a slow machine the time waited by snooze() might not be long enough.
The default way of synchronizing is Based on Object Existance. The waitForObject() function is used before every action that is recorded on an object. On replay, instead of waiting for a specific amount of time, Squish will wait for the given object to exist and be accessible (i.e., visible). Using the waitForObject() function has proved much more reliable than using the snooze(), and it also executes the test case much more quickly.
A third alternative is to use the waitFor(condition, timeout) function. This function waits until a given condition becomes true, or optionally, until a specified timeout expires. The condition can be anything from a property to a complex script statement, but we want to pass it in such a way that it can be evaluated later by waitFor(). Script statements as strings can be used, but we generally prefer lambdas and anonymous functions. Here is an example that waits for a particular dialog to pop up, and logs a fatal error if the dialog doesn't appear within 5 seconds:
ok = waitFor(lambda: object.exists(names.addressBook_saveAs_QFileDialog), 5000) if not ok: test.fatal("AddressBook Save As dialog didn't appear")
var ok = waitFor(function() {object.exists(names.addressBooksaveAsQFileDialog)}, 5000); if (!ok) test.fatal("AddressBook Save As dialog didn't appear");
my $ok = waitFor(sub {object::exists($Names::addressBook_saveAs_QFileDialog)}, 5000); if (!$ok) { test::fatal("AddressBook Save As dialog didn't appear"); }
ok = waitFor(lambda {Object.exists(Names::addressBook_saveAs_QFileDialog)}, 5000) if !ok Test.fatal("AddressBook Save As dialog didn't appear") end
set ok [waitFor {object exists $names::addressBook_saveAs_QFileDialog} \ 5000] if {!$ok} { test fatal "AddressBook Save As dialog didn't appear" }
Here is another example, this time one that will wait "forever" since no timeout is specified. So if the expected file doesn't exist and isn't created, the test script will be stuck:
waitFor(lambda: QFile.exists('addresses.tsv'))
waitFor(function() {QFile.exists('addresses.tsv'))};waitFor(sub {QFile::exists('addresses.tsv'))};waitFor(lambda {QFile.exists('addresses.tsv')})waitFor {invoke QFile exists "addresses.tsv"}This next example waits up to 2 seconds for an OK button to become enabled. The waitFor(condition, timeout) function repeatedly evaluates script code and returns true as soon as the code evaluates to true; or returns false if the code doesn't evaluate to true within the number of milliseconds specified by its second argument.
button = findObject(names::addressBook_AddOK_QPushButton) enabled = waitFor("button.enabled", 2000) if not enabled: test.fatal("OK button has not been enabled")
var button = findObject(names::addressBookAddOKQPushButton); var enabled = waitFor("button.enabled", 2000); if (!enabled) test.fatal("OK button has not been enabled");
my $button = findObject($Names::AddressBook_Add_OK_QPushButton); my $enabled = waitFor(sub {$button->enabled}, 2000); if (!$enabled) { test::fatal("OK button has not been enabled"); }
button = findObject(Names::addressBook_Add_OK_QPushButton) enabled = waitFor("button.enabled", 2000) if !enabled Test.fatal("OK button has not been enabled") end
set button [findObject $names::addressBook_Add_OK_QPushButton] set enabled [waitFor {property get $button enabled} 2000] if {!$enabled} { test fatal "OK button has not been enabled" }
These examples show different variations of synchronization points. As the condition which is passed to the waitFor() function can be any script code which can be evaluated, including function calls, there are no limits to creating synchronization points.
More on synchronization for Web applications and advanced AJAX synchronization can be found at How to Synchronize Web Page Loading for Testing.
By combining the waitFor() function and event handlers (How to Use Event Handlers), it is possible to make the test script execution wait until a specific event has been handled. This can be done by installing an event handler, setting a global variable (e.g. eventHandled) to false, and passing this global variable as condition to the waitFor() function. In the event handler, just set eventHandled to true and you are done.
Using this approach makes it is possible to create completely event driven tests, where the test's main function just installs event handlers and then starts things off by making a call to waitFor(), with all the testing being done inside the event handlers.
© 2025 The Qt Company Ltd.
Documentation contributions included herein are the copyrights of
their respective owners.
The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property
of their respective owners.