Skip to content

Python client

Async (asyncio) client library. This is the reference; for a guided first test see the Python quick start.

Install

bash
pip install vericue              # client + CLI + pytest plugin
pip install vericue[robot]       # + Robot Framework library
pip install vericue[inspector]   # + interactive tree inspector (rich)

Connection lifecycle

VeriCueClient supports async with; connect() performs the protocol handshake automatically before returning.

python
import asyncio
from vericue import VeriCueClient

async def main():
    async with VeriCueClient(timeout=10.0) as client:
        await client.connect("127.0.0.1", 4242, token="optional-secret")
        assert await client.ping()

asyncio.run(main())
  • VeriCueClient(timeout=10.0) - one default timeout (seconds) for both connection and every response.
  • client.is_connected - True while the socket is up.
  • await client.disconnect() - explicit teardown (also done by async with).
  • await client.send_request(method, params) - raw escape hatch for any protocol command; returns the result dict or raises ServerError.

Exceptions

All errors derive from vericue.VeriCueError:

ExceptionRaised when
ConnectionErrorConnect failed, response timed out, server closed the socket
ProtocolErrorMalformed / unexpected message from the server
ServerErrorThe server returned an error - carries .code and .message (see Error codes)

Commands by category

Every method is a coroutine. Paths identify objects, e.g. "MainWindow/centralWidget/okButton".

Object discovery

python
await client.list_objects(object_name=None, class_name=None, root=None, recursive=True)
await client.find_object(path=None, object_name=None, class_name=None)
await client.get_properties(path, properties=None)     # None = all properties
await client.get_children(path, class_name=None)
await client.get_parent(path)
await client.get_object_tree(root=None, depth=-1)       # -1 = unlimited

Interaction

python
await client.mouse_click(path, button="left", click_type="single", x=None, y=None, modifiers=None)
await client.type_text(path, "hello")
await client.key_press(path, "ctrl+s", repeat=1)
await client.drag(path, from_x, from_y, to_x, to_y, button="left", modifiers=None)
await client.scroll(path, dx=0, dy=-3, modifiers=None)
await client.screenshot(path=None)                       # None = first visible window
await client.highlight_object(path, duration=2000, color="red")

Touch & gestures

python
await client.touch_tap(path, x=None, y=None, duration=50)
await client.touch_long_press(path, x=None, y=None, duration=800)
await client.swipe(path, from_x, from_y, to_x, to_y, duration=300, steps=10)
await client.pinch(path, start_distance, end_distance,
                   center_x=None, center_y=None, rotation=0.0, duration=300)
await client.multi_touch(path, touches)   # [{"id": 0, "x": 10, "y": 10, "action": "press"}, ...]

Model/view data

python
await client.get_model_info(path)          # rows, columns, headers, roles
await client.get_model_data(path, row=None, column=None,
                            start_row=None, end_row=None, columns=None, role="display")

Extended automation

python
await client.set_property(path, "text", "new value")
await client.invoke_method(path, "clear")
await client.wait_for_property(path, "enabled", True, timeout=5000, interval=100)
await client.wait_for_signal(path, "clicked()", timeout=5000)

Client-only helpers

These run entirely client-side (no dedicated protocol command):

python
await client.is_visible(path)              # reads the `visible` property
await client.is_enabled(path)              # reads the `enabled` property
await client.save_baseline("baseline.png", path=None)
await client.compare_screenshot_file("baseline.png", path=None,
                                     threshold=0.02, diff_output="diff.png")

Performance

python
await client.frame_time(path=None, duration_ms=1000)    # fps, avg/min/max ms
await client.paint_count(path, duration_ms=1000)
await client.memory_snapshot()                           # rss_bytes, vsize_bytes, threads

Mocking / test helpers

python
await client.emit_signal(path, "timeout()", args=[])
await client.set_clipboard("text")
await client.get_clipboard()

Multi-window

python
windows = await client.list_windows()
# [{objectName, className, path, type: "widget"|"qml", visible, title, active, geometry}, ...]

Push events

Subscribe to Qt-level events; the server pushes them asynchronously (see Push events for the wire format).

python
sub_id = await client.subscribe_signal(path, "clicked()", callback=None)
sub_id = await client.subscribe_property(path, "text", callback=None)
sub_id = await client.subscribe_destroyed(path, callback=None)
await client.unsubscribe(sub_id)
await client.list_subscriptions()

Two consumption styles - a per-subscription callback(event_dict) (sync or async), and the shared queue:

python
event = await client.next_event(timeout=5.0)   # asyncio.TimeoutError on timeout

async for event in client.events():            # iterate everything pushed
    print(event["event"], event["path"], event["data"])

Events are always enqueued for next_event()/events() even when a callback is registered. Subscriptions are cleaned up server-side when the connection closes.

Recording

RecordingSession wraps start_recording/stop_recording as an async context manager and generates a Python script from the captured events:

python
from vericue import RecordingSession

async with RecordingSession(client) as rec:
    input("Interact with the app, then press Enter...")

rec.save_script("recorded_test.py")
print(rec.events)    # raw captured events
print(rec.script)    # generated Python source

See the Recording guide.

Test reporting

TestReporter collects results and renders HTML or JUnit XML:

python
from vericue import TestReporter

reporter = TestReporter(name="Smoke suite")
reporter.start_test("login", "User can log in")
try:
    ...
    reporter.pass_test()
except Exception as e:
    shot = await client.screenshot()
    reporter.fail_test(str(e), screenshot=base64.b64decode(shot["data"]))

reporter.save_html("report.html")
reporter.save_junit_xml("report.xml")     # for CI ingestion

Pytest plugin

Installing the package registers a pytest11 entry point providing three fixtures (vericue_test_app, vericue_client_factory, vericue_client) - see the CI guide for usage.

Robot Framework

pip install vericue[robot] and import vericue.robot.VeriCueLibrary to get 30 veriCue keywords (Click, Type Text, Get Property, ...). The library runs its own asyncio loop in a background thread, so it works with Robot's synchronous execution model.

Multi-process fleets

vericue.multi.MultiVeriCueClient manages a name → client map for testing multi-process Qt systems - see the Multi-process guide.

Released under a commercial licence. Privacy · Terms