Python client
Async (asyncio) client library. This is the reference; for a guided first test see the Python quick start.
Install
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.
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-Truewhile the socket is up.await client.disconnect()- explicit teardown (also done byasync with).await client.send_request(method, params)- raw escape hatch for any protocol command; returns theresultdict or raisesServerError.
Exceptions
All errors derive from vericue.VeriCueError:
| Exception | Raised when |
|---|---|
ConnectionError | Connect failed, response timed out, server closed the socket |
ProtocolError | Malformed / unexpected message from the server |
ServerError | The 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
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 = unlimitedInteraction
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
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
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
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):
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
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, threadsMocking / test helpers
await client.emit_signal(path, "timeout()", args=[])
await client.set_clipboard("text")
await client.get_clipboard()Multi-window
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).
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:
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:
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 sourceSee the Recording guide.
Test reporting
TestReporter collects results and renders HTML or JUnit XML:
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 ingestionPytest 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.

