Skip to content

Recording & replay

veriCue can watch a human interact with the application and turn the session into a runnable Python test script. The recorder is an event filter installed on the application - it observes real input without consuming it, resolves each event's target to a veriCue object path, and emits both a structured event list and generated code.

Quick start

python
from vericue import VeriCueClient
from vericue.recorder import RecordingSession

async with VeriCueClient() as client:
    await client.connect("127.0.0.1", 4242)

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

    print(session.script)                 # generated Python
    session.save_script("recorded_test.py")

Or drive the raw commands directly:

python
await client.start_recording()
# ... user interacts with the app ...
result = await client.stop_recording()

stop_recording returns:

FieldMeaning
eventsStructured event list: {type, path, params, timestamp} per event
scriptReady-to-run Python script using the veriCue client API
event_countNumber of raw events captured (before coalescing)
duration_msRecording length

What gets captured

InputRecorded as
Mouse click (on release)mouse_click with button and local coords
Double clickmouse_click with click_type="double"
Printable typingtype_text - consecutive keystrokes into the same widget are coalesced into one call with the full string
Special keys & shortcutskey_press with combo syntax (enter, tab, ctrl+s, ctrl+shift+z, f1f12, arrows, …)
Mouse wheelscroll with dx/dy in notches

Each event's target is resolved to a path (MainWindow/centralWidget/…) at capture time using the same resolver the rest of veriCue uses, so the generated script replays against the same objects.

A generated script looks like:

python
import asyncio
from vericue import VeriCueClient


async def main():
    async with VeriCueClient() as client:
        await client.connect("127.0.0.1", 4242)

        await client.mouse_click("MainWindow/loginButton")
        await client.type_text("MainWindow/userField", "alice")
        await client.key_press("MainWindow/userField", "tab")
        await client.type_text("MainWindow/passField", "secret")
        await client.key_press("MainWindow/passField", "enter")


asyncio.run(main())

Treat it as a starting point: add assertions (get_properties, wait_for_property, screenshot_compare) after the interactions - a recording captures what you did, not what you expected to see.

Limitations

Be aware of what the recorder does not capture:

  • Touch gestures - only mouse, keyboard, and wheel events are recorded. Swipes/pinches must be scripted by hand (see Touch & gestures).
  • Drags - a press-move-release sequence is recorded as a single click at the release position, not as a drag command.
  • Timing - timestamps are kept in the event list, but the generated script replays as fast as the server accepts commands. Insert wait_for_property / wait_for_signal calls where the app needs time.
  • Modifier-only presses are skipped; unknown special keys outside the supported set (letters, digits-as-text, F-keys, navigation keys) are dropped.
  • Unresolvable targets - events on objects the resolver cannot produce a path for (e.g. transient popups that are gone by resolve time) are skipped.
  • One recording at a time; starting a new one clears the previous buffer.

Workflow tips

  • Record short, focused flows (one scenario per recording) - long sessions produce scripts that are hard to review and brittle to replay.
  • Generated mouse_click calls click the target's center; exact capture coordinates are preserved in the events list if you need them (e.g. for clicks on specific cells of a custom-painted widget).
  • Recordings are a fast way to discover object paths for hand-written tests - even when you discard the generated script itself.

Released under a commercial licence. Privacy · Terms