Testudos features.

What Testudos does and how it works under the hood.

01

What Testudos is

Testudos is a GUI test automation tool for Qt applications. It drives your real application the way a user would and verifies it from the inside, through Qt's own object model.

Qt Quick
QML interfaces, including custom components.
Qt Widgets
Classic desktop and industrial UIs.
Hybrid
Widgets and QML in one application.

Tests are plain pytest.

Standard Python your engineers already write. Fixtures, parametrization, markers, plugins and your existing CI reporting all work as usual.

Extend with any Python.

Check a database, read a log, call a REST service, talk to a serial port or a hardware simulator, all in the same test that drives the UI.

02

Supported platforms

Need something not listed? Ask us.

Area Supported Status
Operating system Windows 11 Supported
Operating system Linux, various distributions Supported
Architecture ARM builds On request
Qt version Qt 6.8 and every later 6.x Supported
Qt version Qt 5.15 and other versions On request
03

How it works: Engine and Agent

Testudos is built from two parts that talk to each other in both directions. No changes to the application under test are required.

CONTROLLED FROM
GUI app CLI pytest
↓
Engine
Runs your tests, manages app sessions and writes the reports. On your desktop or CI server.
127.0.0.1:4322
commands
▶
◀
signals, state, object tree
YOUR QT APPLICATION · unchanged
Agent
A small library injected at launch. Desktop or ARM target.
QML Widgets QObjects

Engine

The orchestrator. It starts or attaches to applications, sends commands, runs your pytest suites and gathers results. You control it from the desktop GUI or from the CLI.

Agent

A dynamic library injected into your application. It listens to Engine commands, dispatches real Qt events, reports signals back and exposes the live object tree for inspection.

04

GUI or command line

Use the desktop app to set up application profiles and watch sessions. Use the CLI to run suites locally or headless in CI.

Testudos desktop app, Run tab: application profile, process status and Engine connection
# run the whole suite
$ testudos run /path/to/tests
============================= test session starts ==============================
collected 42 items

test_alarms.py ........                                           [ 19%]
test_bolus.py .........s..                                        [ 47%]
test_settings.py ......................                             [100%]

=================== 41 passed, 1 skipped in 187.42s ===================
05

Python API

A focused API on top of pytest. See the full reference in the docs →

import pytest
from testudos import App

# find by objectName, by type, by property or by path
def test_bolus_requires_confirmation(app: App):
    dose = app.find("doseInput")
    dose.set_property("text", "2.5")

    with app.expect_signal("pump", "bolusRequested"):
        app.find(type="Button", text="Start bolus").click()

    dialog = app.wait_for("confirmDialog", visible=True)
    assert dialog.property("summary") == "2.5 mL"
Illustrative example. Exact method names are in the API reference.
Find objects
By objectName, type, property values or object path.
Get & set properties
Read state, or drive it directly for setup.
Catch signals
Wait for or assert that a signal was emitted.
User input
Clicks, typing and keys as real Qt events.
Value checks
Assert on text, numbers, visibility and more.
Screenshot comparison
Compare against a baseline image.
06

Inspector

Look under the hood of your running app. Browse the live object tree, select any item and read its properties, types and methods. Search instead of guessing, then copy what you need into a test.

Live object tree of the running app
Properties, types and methods of any object
Search across properties and methods
Optional Qt internals and memory addresses
Testudos Spy tab: object tree of a Qt Quick app with the mainTabBar selected and its properties in the inspector
07

Compliance-ready reports

Every run produces a record you can file, parse or share. Tool version, application build, target and results are captured automatically.

PDF
For the technical file
Readable test records with versions, targets and results.
JSON
For your tools
Machine-readable results for ALM, dashboards and traceability.
HTML
For the team
Browsable reports to share from CI.
08 · MCP SERVER

AI writes more code. QA has to keep up.

Teams ship more code with AI than ever, and every change still needs verifying. Testudos exposes your running app to an AI agent over MCP, so the agent works from the real object tree, not from expensive guesses based on a screenshot. When an interaction works, keep it as a pytest test.

# expose a running application to an agent
$ testudos mcp --port 4242
See what is on screen
object_tree · find_objects
Read it back
get_property · screenshot
Act as a user
click · type_text · key_press
Wait, not sleep
wait_for_property · wait_for_signal
09

Multiple applications at once

One Engine can drive several applications in a single test. Ideal when your product is a system of cooperating apps, or when you test the UI together with a hardware simulator.

Engine
one test session
Main UI
:4400
Service console
:4401
Hardware simulator
:4402
10

Persistent app sessions

attach
Connect to a running app

Attach to an application that is already up, for example one started by a launcher, a service or a long boot sequence on the target.

keep alive
Keep it running after tests

Leave the app open when a test ends, to inspect the final state, debug a failure or chain the next suite without a restart.

11

Testing backend QObjects

Not everything worth testing is on screen. If your C++ classes are registered with Qt's meta-object system, their objects are visible to Testudos: read and set properties, call invokable methods and wait for signals.

pump_controller.h
class PumpController : public QObject {
    Q_OBJECT
    Q_PROPERTY(double rate READ rate
               NOTIFY rateChanged)
public:
    Q_INVOKABLE void stop();
signals:
    void rateChanged();
};
test_backend.py
def test_stop_resets_rate(app):
    pump = app.find("pumpController")
    pump.invoke("stop")
    assert pump.property("rate") == 0
12

How licensing works

Two license types, annual terms. See pricing →

seat
Floating seats

For writing, debugging and running tests. A seat is one concurrent user, not a named person: anyone on the team can use Testudos, the number of seats limits how many at the same time.

runner
CI runners

For executing prepared tests headless in CI pipelines or on dedicated test machines. One runner license per parallel execution.

Hosted license server
All plans
Your machines Testudos cloud

Seats and runners are checked out from the Testudos license server over the internet. Nothing to install or maintain.

Self-hosted license server
Enterprise
Your machines Your license server

Run the license server inside your own network, including offline and air-gapped labs. No outbound connection needed for day-to-day use.

13

Known limitations

We would rather tell you up front. Ping us and we will keep you posted on timelines.

macOS In development

Support for macOS is in development. Contact us and we will share the current timeline.

Android In development

Support for Android targets is in development. Contact us and we will share the current timeline.

iOS In development

Support for iOS targets is in development. Contact us and we will share the current timeline.

Touch gestures Not tested

Multi-touch gestures such as pinch, swipe and long-press have not been validated yet. Single taps and clicks work.

3D items Not tested

Qt Quick 3D scenes and 3D items have not been validated yet. If your UI relies on them, talk to us before you buy.

See it on your own app.

30-day trial. No credit card, no changes to your code.