Squish tip of the week: Resizing a docked window

Resizing a docked window isn’t always as simple as it may seem.
Docked windows often change height and width as well as their docked location. The control or widget can also be more complex, not resizing with a simple MouseDrag used with non-docked windows.

The example below illustrates how to resize a docked window when working with the Qt Widget QDockWidget:

# About Example
# Supply specific QDockWidget's symbolic or real name
# (in this sample application QDockWidget is ColorSwatch)
# change_* functions take three parameters: QDockWidget
# as o, resize value as xdiff, snooze in seconds
# (optional) as snoozeFactor
 
def main():
    startApplication("mainwindow")
 
    dockToResize = waitForObject(":Qt Main Window Demo.White Dock Widget [*]_ColorSwatch")
 
    change_height_on_top(dockToResize, -20)
    change_height_on_top(dockToResize, 20)
    change_height_on_bottom(dockToResize, -20)
    change_height_on_bottom(dockToResize, 20)
    change_width_on_left(dockToResize, -20)
    change_width_on_left(dockToResize, 20)
    change_width_on_right(dockToResize, 20)
    change_width_on_right(dockToResize, -20)
 
def change_height_on_top(o, xdiff, snoozeFactor = 0):
    snooze(snoozeFactor)
    mousePress(o, 50, -2, MouseButton.LeftButton)
    start = 0
    end = xdiff
    step = 1
    if xdiff < 0:
        step = -1
    for i in range(start, end, step):
        mouseMove(o, 50, -2 + i)
    mouseRelease()
    snooze(snoozeFactor)
 
def change_height_on_bottom(o, xdiff, snoozeFactor = 0):
    snooze(snoozeFactor)
    mousePress(o, 50, o.height + 2, MouseButton.LeftButton)
    start = 0
    end = xdiff
    step = 1
    if xdiff < 0:
        step = -1
    for i in range(start, end, step):
        mouseMove(o, 50, o.height + 2 + i)
    mouseRelease()
    snooze(snoozeFactor)
 
def change_width_on_left(o, xdiff, snoozeFactor = 0):
    snooze(snoozeFactor)
    mousePress(o, -3, 50, MouseButton.LeftButton)
    start = 0
    end = xdiff
    step = 1
    if xdiff < 0:
        step = -1
    for i in range(start, end, step):
        mouseMove(o, -3 + i, 50)
    mouseRelease()
    snooze(snoozeFactor)
 
def change_width_on_right(o, xdiff, snoozeFactor = 0):
    snooze(snoozeFactor)
    mousePress(o, o.width + 3, 50, MouseButton.LeftButton)
    start = 0
    end = xdiff
    step = 1
    if xdiff < 0:
        step = -1
    for i in range(start, end, step):
        mouseMove(o, o.width + 3 + i, 50)
    mouseRelease()
    snooze(snoozeFactor)

For more information, and a more extensive example, see Article – Resizing Docked Windows (QDockWidget)

Squish tip of the week: Using your AUT’s toolkit API

With each Squish edition, or technology supported, you can us the corresponding toolkit’s API from your test scripts.

This gives you access to your application, and to make calls, beyond what can be done from your application’s user interface alone.

Take for example the Java Convenience API

In JavaFx applications you can have more than one top-level window.

How can you ensure the proper top-level window is in front before interacting with it? Use the .toFront() call.

For example, given a symbolic name of MyWindow1, the line would simply read MyWindow1.toFront()

Search doc.froglogic.com for your toolkit’s convenience API, or your the AUT toolkit API documentation.

(Near) endless possibilities!

Squish tip of the week: How to spy menu items using Pick tool

Using the Pick tool to spy items which only appear when a parent or related item is first selected may appear impossible, but it’s not!

Imagine you want to verify or inspect an item in a menu, drop down list, context menu, etc. You click the menu, and then the Pick tool. Clicking away makes the menu close. How can you possibly ‘pick’ such an object?

Two options:
  • Option 1: Select the parent item using the Pick tool and manually navigate the Application Objects tree.
  • Option 2: Run the IDE using a remote connection to where the AUT is running and select the menu item using the Pick tool
Option 2: Remote Squish IDE & the Pick tool

As learned in a prior Squish tip of the week, your Squish IDE can create tests and interact with applications through a remote connection. Read more here: Squish tip of the week: Create tests against a remote environment

  1. Once you have the remote connection setup, record a test (or use Launch AUT) using a Squish IDE on a separate computer from the running AUT (this also works with a host computer and virtual machine).
  2. Click the menu in the AUT to display the menu contents.
  3. Return to the computer where the IDE is running and select the Pick tool.
  4. Because these are two different systems, the menu does not close (or disappear) when you click the Pick tool.
  5. Back on the computer where the AUT is running, select the menu item of interest.
Result:

The Squish IDE now displays the menu item in the Application Objects tree with its associated properties and values in the Properties list.

Squish tip of the week: Insert comments while recording

Want to include notes or comments in your script about what you’re recording?

While recording, the Control Bar contains an Insert Script Comment button
insertScriptComment

  1. Click the Insert Script Comment button
  2. The Comment Window appearsInsertCommentWindow
  3. Enter a comment and click OK

Once you complete your recording, by clicking Stop, the comment appears within your script. The following example’s comment is: # Adding a new entry

def main():
    startApplication("AddressBookSwing.jar")
    activateItem(waitForObjectItem(":Address Book_JMenuBar", "File"))
    activateItem(waitForObjectItem(":File_JMenu", "New..."))
    activateItem(waitForObjectItem(":Address Book - Unnamed_JMenuBar", "Edit"))
    activateItem(waitForObjectItem(":Edit_JMenu", "Add..."))
    # Adding a new entry
    type(waitForObject(":Address Book - Add.Forename:_JTextField"), "sam")
    type(waitForObject(":Address Book - Add.Forename:_JTextField"), "<Tab>")
    type(waitForObject(":Address Book - Add.Surname:_JTextField"), "smith")
    type(waitForObject(":Address Book - Add.Surname:_JTextField"), "<Tab>")
    type(waitForObject(":Address Book - Add.Email:_JTextField"), "sam@smith.com")
    type(waitForObject(":Address Book - Add.Email:_JTextField"), "<Tab>")
    type(waitForObject(":Address Book - Add.Phone:_JTextField"), "123.123.1234")
    clickButton(waitForObject(":Address Book - Add.OK_JButton"))

Squish tip of the week: How does Squish find objects?



A critical component to any automated gui testing solution is how objects are identified and interacted with

Squish uses the Object Map to store select properties, and their values or othe object real name, which is then referenced by scripts using a symbolic name.

Example: An OK button

Real name
{text='Yes' type='QPushButton' unnamed='1' 
  visible='1' window=':Address Book - Delete_QMessageBox'}
Symbolic name
:Address Book - Delete.Yes_QPushButton
Object Map Entry

click to zoom

(more…)

Squish tip of the week: Handling implementation differences between platforms

A great question from our Webinar Q&A session this week: What is the best way to solve implementation differences between platforms (e.g. Windows Vs Unix)?

When dealing with cross-platform applications, for example Java or Qt, the majority of your Squish tests are not impacted by the platform, as your application, and it’s controls/widgets are identical across platforms. Occasionally however differences may exist.

Using Squish there’s an easy way to handle platform differences: Identify and branch for differences

Example working with Java Applications

You can try it using our sample Addressbook application, located in:
<squishDir>\examples\java\addressbook

In the following script (javascript), lines 12 and 13 are valid for Linux and Windows, but not valid for Mac:

function main() {
    startApplication("AddressBookSwing.jar");
    activateItem(waitForObjectItem(":Address Book_javax.swing.JMenuBar", "File"));
    activateItem(waitForObjectItem(":File_javax.swing.JMenu", "New..."));
    activateItem(waitForObjectItem(":Address Book - Unnamed_javax.swing.JMenuBar", "Edit"));
    activateItem(waitForObjectItem(":Edit_javax.swing.JMenu", "Add..."));
    type(waitForObject(":Address Book - Add.Forename:_javax.swing.JTextField"), "jane");
    type(waitForObject(":Address Book - Add.Surname:_javax.swing.JTextField"), "smith");
    type(waitForObject(":Address Book - Add.Email:_javax.swing.JTextField"), "jane@smith.com");
    type(waitForObject(":Address Book - Add.Phone:_javax.swing.JTextField"), "123.123.1234");
    clickButton(waitForObject(":Address Book - Add.OK_javax.swing.JButton"));
    activateItem(waitForObjectItem(":Address Book - Unnamed_javax.swing.JMenuBar", "File"));
    activateItem(waitForObjectItem(":File_javax.swing.JMenu", "Quit"));
    clickButton(waitForObject(":Address Book.No_JButton"));
}

To accommodate the platform difference we’ll:

  1. Check the platform prior to the impacted steps
  2. Branch the script to take one path when the platform is Mac, and another path it isn’t

Which results in the following:

function main() {
    startApplication("AddressBookSwing.jar");
    activateItem(waitForObjectItem(":Address Book_javax.swing.JMenuBar", "File"));
    activateItem(waitForObjectItem(":File_javax.swing.JMenu", "New..."));
    activateItem(waitForObjectItem(":Address Book - Unnamed_javax.swing.JMenuBar", "Edit"));
    activateItem(waitForObjectItem(":Edit_javax.swing.JMenu", "Add..."));
    type(waitForObject(":Address Book - Add.Forename:_javax.swing.JTextField"), "jane");
    type(waitForObject(":Address Book - Add.Surname:_javax.swing.JTextField"), "smith");
    type(waitForObject(":Address Book - Add.Email:_javax.swing.JTextField"), "jane@smith.com");
    type(waitForObject(":Address Book - Add.Phone:_javax.swing.JTextField"), "123.123.1234");
    clickButton(waitForObject(":Address Book - Add.OK_javax.swing.JButton"));
    if (java_lang_System.getProperty("os.name").indexOf("Mac OS") == 0) {
        nativeType("<Command+q>");
    } else {
        activateItem(waitForObjectItem(":Address Book - Unnamed_javax.swing.JMenuBar", "File"));
        activateItem(waitForObjectItem(":File_javax.swing.JMenu", "Quit"));
    }
    clickButton(waitForObject(":Address Book.No_JButton"));
}

Notice, line 12 in the modified script retrieves the platform where the application is *currently* executing. This is important, as the test may be triggered by a remote system using another platform.

Example working with Qt Applications

You can try it using our sample Addressbook application, located in:
<squishDir>\examples\java\addressbook

In the following script (javascript), lines 10 and 11 are valid for Linux and Windows, but not valid for Mac:

function main() {
    startApplication("addressbook");
    clickButton(waitForObject(":Address Book.New_QToolButton"));
    clickButton(waitForObject(":Address Book - Unnamed.Add_QToolButton"));
    type(waitForObject(":Forename:_LineEdit"), "jane");
    type(waitForObject(":Surname:_LineEdit"), "smith");
    type(waitForObject(":Email:_LineEdit"), "jane@smith.com");
    type(waitForObject(":Phone:_LineEdit"), "123.123.1234");
    clickButton(waitForObject(":Address Book - Add.OK_QPushButton"));
    activateItem(waitForObjectItem(":Address Book - Unnamed_QMenuBar", "File"));
    activateItem(waitForObjectItem(":Address Book - Unnamed.File_QMenu", "Quit"));
    clickButton(waitForObject(":Address Book - Delete.No_QPushButton"));
}

To accommodate the platform difference we’ll:

  1. Check the platform prior to the impacted steps
  2. Branch the script to take one path when the platform is Mac, and another path it isn’t

Unlike in Java, where the host platform is available with the java_lang_System.getProperty(“os.name”) statement, for Qt the platform should be passed to the squishrunner service when started.

For example, you may start your squishserver using the following commands:
export SQUISH_HOST_OS=`uname`
./squishserver

For Windows, use ver instead of uname:

for /f "delims=" %a in ('ver') do @set SQUISH_HOST_OS=%a
squishserver.exe

Then modify the script as follows:

function getHostOS(){
    myAUT = currentApplicationContext();
    hostOS = myAUT.environmentVariable("SQUISH_HOST_OS");
    return hostOS
}

function main() {
    startApplication("addressbook");
    clickButton(waitForObject(":Address Book.New_QToolButton"));
    clickButton(waitForObject(":Address Book - Unnamed.Add_QToolButton"));
    type(waitForObject(":Forename:_LineEdit"), "jane");
    type(waitForObject(":Surname:_LineEdit"), "smith");
    type(waitForObject(":Email:_LineEdit"), "jane@smith.com");
    type(waitForObject(":Phone:_LineEdit"), "123.123.1234");
    clickButton(waitForObject(":Address Book - Add.OK_QPushButton"));
    
    if (getHostOS() == "Darwin"){
        nativeType("<Command+q>")
    } else{
        activateItem(waitForObjectItem(":Address Book - Unnamed_QMenuBar", "File"));
        activateItem(waitForObjectItem(":Address Book - Unnamed.File_QMenu", "Quit"));
    }
    
    clickButton(waitForObject(":Address Book - Delete.No_QPushButton"));
}

Notice, line 3 in the modified script retrieves the platform where the application is *currently* executing using the value set in the environment variable before starting the squish server. This is important, as the test may be triggered by a remote system using another platform.

Come see froglogic at EclipseCon North America 2015

froglogic will be at the EclipseCon North America 2015 conference in San Francisco, California, Monday, March 9th through Wednesday, March 11th.

Stop by our booth for a live demo of Squish GUI Tester!

If you would like to schedule a meeting at the EclipseCon North America with a representative of froglogic, please contact us.

For more information see https://www.eclipsecon.org/na2015/.

Squish tip of the week: The power of Symbolic Names

The use of Symbolic Names in scripts is key when creating a maintainable Automated Test Framework.

Imagine the following scenario:
  1. You create a set of 10 tests, or 10,000 tests
  2. A common set of controls (buttons, text fields, etc.) are used through out many of the tests
  3. New release! One (or more) of those commonly used controls changed between releases

(more…)