Guides
SAP GUI for Windows
dolphin can automate classic SAP GUI for Windows through the SAP GUI Scripting
COM API. This is separate from the uia and win32 backends because SAP exposes
stable component IDs and session objects through its own automation model.
Requirements
- SAP GUI for Windows is installed and running.
- SAP GUI Scripting is enabled in the local SAP GUI client options (Options → Accessibility & Scripting → Scripting → Enable scripting).
- SAP GUI Scripting is allowed by the target SAP system: profile
parameter
sapgui/user_scripting = TRUE(set it in RZ11 for the running instance, or in the instance profile via RZ10 to make it survive a restart). Without it the scripting engine still attaches and lists the connection, but the connection exposes zero sessions — which is the usual reason a working setup suddenly finds nothing. - Tests run on Windows with
pywin32available.
The scripting-security notification
By default SAP GUI raises a modal notification the first time a script attaches ("A script is trying to attach to SAP GUI"). It is modal to the scripting call, so an unattended run stalls behind it.
SapGui.scripting_security_handler() starts a background thread that
confirms exactly that dialog — start it before connecting, since the
dialog blocks the attach itself:
stop = SapGui.scripting_security_handler()
try:
sap = SapGui.connect(timeout=30)
...
finally:
stop.set()
To silence the prompts for good on a dedicated test machine, clear Notify when a script attaches to SAP GUI and Notify when a script opens a connection in the same SAP GUI options page.
Basic Usage
from dolphin_desktop import SapGui
sap = SapGui.connect()
session = sap.session(connection=0, session=0)
session.transaction("SE16")
session.find_by_id("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").set_text("T000")
session.find_by_id("wnd[0]/tbar[1]/btn[8]").click()
assert session.find_by_id("wnd[0]/sbar").text() is not None
You can also connect through Desktop when a test already uses Dolphin desktop
fixtures:
def test_sap_from_desktop(desktop):
sap = desktop.sap()
session = sap.session()
session.transaction("VA03")
Locators
SAP component IDs are the preferred selector. They are the same IDs visible in
SAP GUI Scripting recordings and usually look like wnd[0]/usr/....
customer = session.find_by_id("wnd[0]/usr/ctxtVBAK-KUNNR")
customer.set_text("100000")
assert customer.value() == "100000"
SapLocator is lazy: dolphin does not query SAP until an action or assertion is
called. Actions wait for session.Busy to become false and retry until the
configured Dolphin timeout expires.
Finding Component IDs (Spy)
The regular uia/win32 Object Spy cannot see SAP component IDs — SAP GUI is
opaque to the UIA tree. Use the SAP-aware spy instead, which drives SAP GUI
Scripting directly and emits find_by_id(...) locators.
# Print the SAP component tree of the active session
dolphin spy --sap
# Pick a control interactively (Ctrl+Click highlights and captures it)
dolphin spy --sap --pick
# Select a non-default connection/session, limit depth, or emit JSON
dolphin spy --sap --connection 0 --session 0 --depth 4
dolphin spy --sap --json
The headless Python API mirrors the desktop spy:
import dolphin_desktop.spy as spy
tree = spy.sap_inspect() # {"schema_version": 1, "root": {...}}
print(spy.format_sap_tree(tree["root"]))
picked = spy.sap_pick()
# {"schema_version": 1, "status": "ok",
# "selector": {"id": "wnd[0]/usr/ctxtVBAK-KUNNR"}, "message": ""}
if picked["status"] == "ok":
sel = picked["selector"]
Each node exposes the session-relative id (the locator Dolphin uses), the
absolute full_id, plus name, type, text, bounding_box, and
changeable. The id is the most stable selector, so sap_pick() returns it
whenever a control exposes one.
status is "ok", "cancelled" (Esc) or "no_session"; selector is empty
for anything but "ok". Check it rather than assuming a pick succeeded —
sap_inspect() carries the same schema_version, so a tool consuming either
can detect a format change.
Transactions And Keys
transaction("SE16") writes /nSE16 to the OK Code field and sends Enter.
For lower-level key handling, use SAP virtual keys:
session.send_vkey("ENTER")
session.send_vkey("F8")
session.find_by_id("wnd[0]/usr/ctxtFIELD").press_key("F4")
Common aliases include ENTER, F3/BACK, F8/EXECUTE, F11/SAVE, and
F12/CANCEL.
Raw COM Access
When a SAP control needs a method that Dolphin does not wrap yet, resolve the component and use the underlying COM object:
grid = session.find_by_id("wnd[0]/usr/cntlGRID1/shellcont/shell").raw
grid.currentCellRow = 0
grid.selectedRows = "0"
This is useful for ALV grids and custom SAP controls. Dedicated high-level grid helpers are intentionally outside the first SAP support version.
Running the bundled SAP suite
tests/sap/ drives a live system and keeps every credential out of the
repository — it reads them from the environment and skips when they are
missing:
| Variable | Meaning |
|---|---|
DOLPHIN_SAP_USER |
logon user |
DOLPHIN_SAP_PASSWORD |
logon password |
DOLPHIN_SAP_CLIENT |
client / mandant, e.g. 001 |
DOLPHIN_SAP_LANG |
logon language (default EN) |
DOLPHIN_SAP_CONNECTION |
SAP Logon entry to open when no session is running |
$env:DOLPHIN_SAP_USER = "..."; $env:DOLPHIN_SAP_PASSWORD = "..."
$env:DOLPHIN_SAP_CLIENT = "001"
pytest tests/sap -v
The fixtures attach to a running SAP GUI and sign in only when the session sits on the logon screen, so an already-signed-in session is used as-is and never disturbed. Every test in the suite is display-only.
Notes
- A runnable example that attaches to an already-open SAP GUI session
lives at
examples/sap_gui/test_sap_gui.py. - SAP GUI Scripting is session-global; avoid running SAP GUI tests in parallel against the same desktop session.
- If
SapGui.connect()fails, confirm that SAP GUI is already running and that scripting is enabled on both the client and server. - SAP Business Client and browser-based SAP apps are not covered by this API.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
SapConnection: could not attach to running SAP GUI |
SAP GUI is not running, or scripting is disabled on the client | Launch SAP Logon → Options → Accessibility → Scripting → Enable scripting; uncheck "Notify when a script attaches" and "Notify when a script opens a connection" |
SapGui.connect(): timeout waiting for GuiApplication |
Multiple SAP GUI processes; COM binds to the wrong one | Close every SAP GUI window, relaunch the one you want tested, then run the test |
permission denied on sap.connections() |
Server-side scripting disabled | Have Basis enable in RZ11: sapgui/user_scripting = TRUE, sapgui/user_scripting_disable_recording = FALSE |
SapLocator returns None for a visible field |
Field is inside a nested GuiShell tree |
Use the full ID from the SAP recorder — dolphin's fuzzy matching does not cross shell boundaries |
| Test kills the user's SAP session on teardown | The SAP GUI process is on dolphin's per-test kill list | dolphin only reaps processes it launched, so attach rather than launch SAP GUI; if you did launch it, call app.detach(session=True) on that Application |
cell_value() returns empty for numeric cells |
SAP represents empty and zero differently per column | Read the column with cell_value(row, column) and compare against "" explicitly rather than truthiness |
| Text shows Unicode boxes | Windows locale lacks the SAP session codepage | Install the matching Windows language pack or use session.system_info()["language"] to detect and skip |