Squish GUI Testing: Automated Tests for Qt, Web, and Desktop Apps

Squish GUI Testing: Automated Tests for Qt, Web, and Desktop Apps

Web browser automation gets most of the attention in test tooling, but a significant portion of enterprise software runs as desktop applications — Qt apps, Java Swing interfaces, Windows desktop software. These need automated testing too, and Squish is one of the most capable tools for the job.

This guide covers Squish GUI testing for teams dealing with Qt applications, cross-platform desktop software, or web applications that need deeper automation than browser-based tools provide.

What Is Squish?

Squish is a GUI test automation tool developed by Froglogic (now part of Keysight). It supports automated testing of:

  • Qt applications (the primary use case — Squish has the deepest Qt support of any test tool)
  • Java AWT/Swing/SWT applications
  • Web applications (via embedded browser or external browser)
  • Windows native apps (Win32, MFC, WPF, WinForms)
  • macOS native apps
  • Embedded/HMI systems

Squish works by hooking into the application at a low level, accessing the actual UI object tree rather than taking screenshots and doing pixel matching. This makes tests more reliable across screen sizes and themes.

Architecture Overview

Squish has a client-server architecture:

  • Squish Server: Runs alongside your application under test (AUT). Injects hooks, exposes the object tree.
  • Squish IDE: Where you write, record, and manage tests (Eclipse-based)
  • squishrunner: Command-line test runner for CI/CD
  • Test scripts: Python, JavaScript, Perl, Ruby, or Tcl

Tests communicate with the Squish Server to find objects, trigger interactions, and read property values.

Installation and Setup

  1. Download Squish for your platform (Linux, Windows, macOS) and target technology (Qt, Java, Web, etc.)
  2. Start squishserver — runs on port 4322 by default
  3. Register your application — tell Squish where the AUT executable is
  4. Open Squish IDE and create a new test suite

For Qt applications specifically, Squish requires the Qt binaries be accessible. On Linux:

export SQUISH_PREFIX=/opt/squish
export PATH=$SQUISH_PREFIX/bin:$PATH
squishserver --startservice

Writing Your First Test

Tests can be recorded or written manually. Here's a Python test for a Qt desktop application:

import test
import testData
import object
import objectMap
import names

def main():
    # Start the application under test
    startApplication("my_app")
    
    # Find and interact with UI elements
    clickButton(waitForObject(names.login_button))
    
    # Type into a text field
    type(waitForObject(names.username_field), "testuser")
    type(waitForObject(names.password_field), "password123")
    
    # Click login
    clickButton(waitForObject(names.submit_button))
    
    # Assert the dashboard is visible
    waitForObject(names.dashboard_widget)
    test.verify(
        findObject(names.dashboard_widget).visible,
        "Dashboard is visible after login"
    )
    
    # Assert the username is displayed
    username_label = waitForObject(names.username_label)
    test.compare(username_label.text, "testuser", "Username displayed correctly")

The names module references the Object Map — a central registry of UI elements and their locator strategies.

The Object Map

The Object Map is central to Squish test maintenance. Instead of hardcoding element locators in each test, you define them once in the Object Map and reference them by name.

Example Object Map entry for a Qt button:

{
  "login_button": {
    "type": "QPushButton",
    "text": "Login",
    "container": "main_window"
  }
}

Benefits:

  • Change a locator in one place when the UI changes
  • Tests stay readable (names like names.login_button are more meaningful than raw locators)
  • Squish IDE shows Object Map as a tree, making it easier to navigate

Qt-Specific Testing

For Qt apps, Squish has deep access to Qt's object hierarchy. You can query and interact with any QObject property:

# Get a property value from a Qt widget
button = waitForObject(names.my_button)
is_enabled = button.enabled
button_text = button.text

# Interact with a QComboBox
combo = waitForObject(names.my_combo)
selectOption(combo, "Option 2")

# Check model data in a QTableView
table = waitForObject(names.data_table)
row_count = table.model().rowCount()
cell_value = table.model().index(0, 0).data()
test.compare(cell_value, "Expected Value", "First cell contains correct data")

# Interact with custom Qt widgets
custom_widget = waitForObject(names.custom_calendar)
invokeMethod(custom_widget, "selectDate", toDate("2026-01-15"))

This depth of Qt integration is Squish's main differentiator. Selenium or Playwright cannot introspect native Qt widget properties — they only see the rendered output.

Cross-Platform Testing

One of Squish's strengths is running the same test suite against the same application on multiple platforms. Since Squish interacts through the Qt layer (not platform-specific APIs), a test written for Linux usually runs on macOS and Windows with minimal modification.

For platform-specific variations:

import sys

def main():
    startApplication("my_app")
    
    if sys.platform == "win32":
        # Windows-specific path
        file_path = "C:\\Users\\test\\documents\\test.txt"
    else:
        file_path = "/home/test/documents/test.txt"
    
    type(waitForObject(names.file_path_input), file_path)

Web Testing with Squish

Squish supports testing web applications through embedded browsers in desktop apps (common in Qt apps using QWebEngine or QtWebView) and through external browsers.

For Qt apps with embedded web views, Squish treats the web content as part of the application's object tree — you can switch contexts:

def main():
    startApplication("my_hybrid_app")
    
    # Interact with native Qt UI
    clickButton(waitForObject(names.open_web_view_button))
    
    # Switch to web context
    web_view = waitForObject(names.web_engine_view)
    
    # Find elements inside the web view
    link = waitForObject({"type": "QWebEngineView", "tagName": "A", "innerText": "Dashboard"})
    click(link)

Handling Asynchronous Operations

Desktop apps, like web apps, often have operations that take time. Squish's waitForObject handles this:

# Wait up to 10 seconds for element to appear
result_label = waitForObject(names.result_label, 10000)

# Wait for a property to reach a value
def wait_for_enabled(object_name, timeout=5000):
    deadline = time.time() + timeout / 1000
    while time.time() < deadline:
        obj = findObject(object_name)
        if obj.enabled:
            return obj
        snooze(0.1)
    raise Exception(f"Timeout waiting for {object_name} to be enabled")

CI/CD Integration

Run Squish tests headlessly in CI using squishrunner:

squishrunner \
  --host localhost \
  --port 4322 \
  --testsuite /path/to/test/suite \
  --reportgen xml,/path/to/results.xml \
  --exitCodeOnFail 1

GitHub Actions example for Qt desktop app tests:

name: GUI Tests
on: [push, pull_request]

jobs:
  gui-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y xvfb libxcb-xinerama0

      - name: Start Squish server
        run: |
          /opt/squish/bin/squishserver --startservice &
          sleep 3

      - name: Run tests
        run: |
          export DISPLAY=:99
          Xvfb :99 -screen 0 1024x768x24 &
          /opt/squish/bin/squishrunner \
            --host localhost \
            --port 4322 \
            --testsuite tests/main \
            --reportgen xml,results/report.xml \
            --exitCodeOnFail 1

      - name: Upload results
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: test-results
          path: results/

Data-Driven Tests

Squish supports data-driven testing through test data files:

# testData module provides access to data files
def main():
    dataset = testData.dataset("test_data.tsv")
    
    for row in dataset:
        startApplication("my_app")
        
        type(waitForObject(names.input_field), testData.field(row, "input"))
        clickButton(waitForObject(names.calculate_button))
        
        result = waitForObject(names.result_label)
        expected = testData.field(row, "expected_output")
        test.compare(result.text, expected, f"Result for input {testData.field(row, 'input')}")
        
        closeApplication()

The data file (test_data.tsv):

input	expected_output
100	200
0	0
-50	error

Performance Considerations

GUI tests are slower than unit tests by nature. Strategies for keeping test time manageable:

Parallel execution: Run independent test suites simultaneously using multiple Squish server instances. Squish supports parallel runs through its commercial licensing.

Application state shortcuts: Instead of clicking through the UI to reach a specific state, use the application's command-line arguments or API to set state directly, then test from that point.

Focus on critical paths: Automate the high-value, frequently-run paths. Not every test needs to go through the full UI.

Reuse test components: Squish supports shared script libraries. Factor common operations (login, navigation, teardown) into reusable functions.

Squish vs Alternatives for Desktop Testing

vs AutoIt: AutoIt uses image recognition and Windows API calls. Squish has deeper access to Qt internals. AutoIt is free; Squish is commercial.

vs WinAppDriver: Microsoft's WinAppDriver targets Windows native apps using the WebDriver protocol. Good for Windows-only apps. Squish supports cross-platform and Qt-specific access that WinAppDriver lacks.

vs Ranorex: Both are commercial GUI automation tools. Ranorex is more focused on the Windows desktop ecosystem. Squish has superior Qt support and better cross-platform coverage.

vs Selenium/Playwright for hybrid apps: If your desktop app embeds a web view and most of your test area is the web content, browser-based tools may be simpler. Squish is better when significant functionality is in the native Qt portions.

When to Use Squish

Squish is the right choice when:

  • Your application is built with Qt
  • You need cross-platform desktop automation
  • Your app contains embedded web views mixed with native Qt widgets
  • You need to introspect widget properties, not just click through the UI
  • Enterprise support and documentation are important

For pure web applications, Playwright or Cypress are simpler and better supported. For pure Windows apps, WinAppDriver or Ranorex may be sufficient. Squish excels at the complex, cross-platform, Qt-heavy scenarios where other tools fall short.

Summary

Squish provides deep GUI automation for Qt applications and cross-platform desktop software. Its access to the Qt object tree, support for multiple scripting languages, and cross-platform consistency make it the standard choice for Qt application testing.

The learning curve is steeper than web testing tools, and the commercial licensing is a cost to factor in. For teams with Qt applications that need solid automated regression coverage, Squish is typically the right tool.

Read more

Start now free