In Appium, how does a test call a driver's mobile: command through java-client or the Python client?
answer
- no typed method exists
- script-execution call, not a helper
- the name is the script string
- one map, one argument
basics
~10 sThrough the client's script-execution call - executeScript in Java, execute_script in Python - passing the command name as the script string and exactly one parameter map as the single argument the driver reads.
solid answer
~40 sAppium's drivers expose most of their non-standard behaviour as **execute methods** whose names begin with `mobile:`. Neither client gives those dedicated typed methods, so you reach them through the script-execution surface the client already inherits from Selenium: in Java `driver.executeScript("mobile: deviceInfo")`, in Python `driver.execute_script('mobile: deviceInfo')`. Parameters go in **one** map or dict passed as the single script argument — not as several positional arguments, and not wrapped in a list. The client serialises the name and that one object and sends them to `POST /session/:sessionId/execute/sync`, where the driver that owns the name unpacks the map. Names belong to drivers, not to the client: `mobile: deviceInfo` is Android's UiAutomator2 driver's and `mobile: getAppearance` is Apple's XCUITest driver's, and the client knows that neither exists.
code
python · 15 linesfrom appium import webdriver
from appium.options.android import UiAutomator2Options
options = UiAutomator2Options()
options.platform_name = "Android"
options.automation_name = "UiAutomator2"
options.app = "/builds/physio-exercise-app.apk"
driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
try:
# The name is the script string; parameters would go in ONE dict argument
info = driver.execute_script("mobile: deviceInfo")
print(info)
finally:
driver.quit()go deeper
Know that a mobile: command is invoked through executeScript in Java or execute_script in Python, with the command name as the script string. There is no dedicated client method to go looking for.
Explain that the name and one parameter map are serialised and sent to the session's driver, which unpacks the map. Be ready to say why parameters must be a single object rather than several arguments.
Diagnose an unknown-method error as a driver mismatch rather than a client bug, and know that Android's UiAutomator2 driver and Apple's XCUITest driver publish different command names for comparable work.
Own the policy for how much raw, driver-specific execute usage is allowed in a suite and how a command rename should propagate, given that the client can warn you about neither.
## The two command surfaces a client faces An Appium session answers two different kinds of command, and the clients treat them very differently. The first kind is the standard W3C WebDriver set — find an element, click it, read its text, take a screenshot. That set is small, stable and shared by every remote end, so every client wraps it in ordinary typed methods. The second kind is each driver's own **execute methods**: names beginning with `mobile:` that cover the work which only makes sense on a device. The clients deliberately do not wrap these. There is no `driver.deviceInfo()` in `java-client` and no `driver.device_info()` in Appium's Python client. You reach them through the script-execution call instead. ## The exact call shape There are three things to get right and no more: - **The name** goes in the script string, complete with its `mobile:` prefix and the single space after the colon. - **The parameters**, if the command takes any, all go into **one** map or dict. - **That map is the single argument** — the first and only script argument. In Java that reads `driver.executeScript("mobile: deviceInfo")` for a command with no parameters, and `driver.executeScript("mobile: pressKey", Map.of("keycode", 4))` against Android's UiAutomator2 driver for one that takes them. In Python the same two calls are `driver.execute_script('mobile: deviceInfo')` and `driver.execute_script('mobile: pressKey', {'keycode': 4})`. The client serialises those two values and sends them to `POST /session/:sessionId/execute/sync`, where the driver that owns the name unpacks the map and does the work. ## Why the parameters must be one object This is where the mistake actually happens. Selenium's script-execution methods take a variadic argument list, so writing two parameters as two arguments feels natural. Appium's execute methods do not work that way: the driver reads the **first** script argument and treats that single object as the whole parameter set. - One map or dict, as the single argument — correct. - Several positional arguments — only the first is read; the rest are silently dropped. - A list wrapping the map — the driver receives an ordered list where it expected named keys. - Python keyword arguments — they are not script arguments at all, so the driver never sees them. The silent-drop case is the nastiest, because the command still runs; it just runs with defaults where you thought you had set something. ## Names belong to drivers, not to the client | | Standard W3C commands | Driver `mobile:` commands | |---|---|---| | Typed client method | yes | no | | Name checked when you build | yes | no — it is a string | | Owner | the protocol, shared by all drivers | one driver at a time | | A misspelling surfaces | as a compile or attribute error | as a server error at run time | That last row is the practical consequence. Because the name is a string, nothing in your build can check it. A misspelling — or a name owned by a driver your session is not using — produces a server-side error at run time naming the method it could not find. Two habits follow: 1. Read the Appium server log, not only the client exception, when an execute call fails. 2. Check which driver the session was created with before assuming the command is broken. Android's drivers and Apple's XCUITest driver publish different names for comparable work, and a name from one is simply unknown to the other. ## A worked case A suite for a physiotherapy exercise app wants to record which device answered a failing repetition-count assertion. There is no client method for that, so the test calls `mobile: deviceInfo` on Android's UiAutomator2 driver and logs the returned map. The call is one line. The interesting part is what was *not* needed: no client upgrade, no new dependency, no typed helper — because the client only ever had to carry a string and hand back parsed JSON. ## The rule to carry away One name, one map, one argument. The client validates none of it, which is exactly what makes the surface useful: a driver can add a command tomorrow and the client you already have can call it today. The cost of that flexibility is that every check you would like the compiler to do for you happens on the server instead, and shows up in the server's log rather than in your build output.
- What happens when the mobile: name is not one the session's driver owns?The server rejects it and the error names the unknown method. Nothing fails when you build, because the client only ever saw a string. Check which driver created the session: Android's UiAutomator2 driver and Apple's XCUITest driver expose different `mobile:` names, so a name from one is unknown to the other.
- Why does java-client not simply add a typed method for every mobile: command?Because those commands belong to drivers that ship on their own schedules, and there are hundreds of them across Android's and Apple's drivers. Freezing that list into client methods would make the client lag every driver release. The untyped call lets a driver add a command that existing client versions can already reach.
saying these in an interview costs you the question
- Passes each parameter as a separate positional argument
- Wraps the parameter map in a list before sending it
- Expects a typed client method for every mobile: command
- Assumes every mobile: name works on both Android and Apple drivers
- Thinks a build error will catch a misspelled mobile: name