3.9 KiB
3.9 KiB
1. Verify Appium UiAutomator2 command surface
- 1.1 Read the installed
Appium-Python-ClientUiAutomator2 driver source/docs (appium.options.android.uiautomator2,appium.webdriverextensions) to confirm the exact mobile-command names and parameters for: a tap/click gesture at a coordinate, a coordinate-to-coordinate swipe/drag with duration, and a home-button press. Confirm the exact capability key name for per-session port isolation (UiAutomator2's analog to WDA'swdaLocalPort).
2. Driver implementation
- 2.1 Add
driver/android_driver.pywithAndroidDriverConfig(frozen dataclass):server_url(defaulthttp://127.0.0.1:4723),platform_name(default"Android"),automation_name(default"UiAutomator2"),device_name,udid,system_port,no_reset(defaultTrue),extra_capabilities. - 2.2 Implement
AndroidDriver(Driver).connect()/disconnect()usingappium.webdriver+UiAutomator2Options, building capabilities the same wayWDADriver.connect()does, with the same_require_client()guard andDeviceOfflineErroron connect failure. - 2.3 Implement
screenshot(),tree(),input(),launch(),terminate(),lock(),unlock()using the same cross-platform Appium client methodsWDADriveralready uses (get_screenshot_as_png,page_source,switch_to.active_element.send_keys,activate_app,terminate_app,lock,unlock). - 2.4 Implement
tap(),swipe(),home()using the mobile-command names/parameters confirmed in task 1.1. - 2.5 Wrap every method's underlying exception into
DriverError(DeviceOfflineErrorfor connect failure and for calls made before a client exists), matchingWDADriver's try/except-per-method pattern exactly.
3. Registry wiring
- 3.1 Add
build_android_driver_factorytodriver/registry.py, mirroringbuild_wda_driver_factory's logic for splittingconnection_infointo declaredAndroidDriverConfigfields vs.extra_capabilities. - 3.2 Register
SUPPORTED_DRIVER_TYPES["uiautomator2"] = build_android_driver_factory.
4. Unit tests
- 4.1 Add mocked unit tests for
AndroidDriver(mockappium.webdriver.Remote, no real device/emulator) covering: connect builds a client with the expected capabilities from a givenAndroidDriverConfig; connect failure raisesDeviceOfflineError; calling any operation beforeconnect()raisesDeviceOfflineError; each operation's underlying exception is wrapped intoDriverError. - 4.2 Add a unit test for
build_android_driver_factorycoveringconnection_infofield extraction andextra_capabilitiesmerging (mirrorbuild_wda_driver_factory's existing test coverage if any exists; if none exists today, note that in the test file rather than silently skipping equivalent WDA coverage).
5. Integration test
- 5.1 Add
tests/test_android_integration.pymirroringtests/test_wda_integration.py's structure:@pytest.mark.integration,pytest.skipwhenAPEX_ANDROID_SERVER_URLis unset, optionalAPEX_ANDROID_UDID/APEX_ANDROID_DEVICE_NAME, connects and asserts a non-emptyscreenshot()before disconnecting.
6. Spec and docs
- 6.1 Confirm
openspec/changes/android-driver/specs/driver-registry/spec.md'sdriver_type="uiautomator2"scenario still matches the shipped registry key and behavior exactly; update the delta if anything changed during implementation (e.g. the system-port capability name). - 6.2 Correct
docs/MACOS_IPHONE_SETUP.md§1: replace "Android 只是架构上的未来目标,当前 driver/registry.py 没有注册 Android Driver" with an accurate statement that the Android driver is registered, while a full real-device setup guide remains separate follow-up work.
7. Verification
- 7.1 Run
uv run --all-packages pytest -m "not integration"and confirm no regressions. - 7.2 Run the project's lint/format checks against the new files and fix any violations.
- 7.3 Run
openspec validate android-driver --strictand confirm it passes.