Cross-platform device automation for end-to-end test workflows
Project description
idevice
Cross-platform device automation for end-to-end test workflows: install and manage apps on physical devices, transfer files, and drive UI interactions through a small, platform-agnostic API.
Platform status
| Platform | Backend | App lifecycle | File transfer | Documents sandbox | Swipe | UI automation |
|---|---|---|---|---|---|---|
| iOS | go-ios (IOSDevice) |
Yes | Yes | — | — | Planned (WDA) |
| iOS | pymobiledevice3 (IOSDevice3) |
Yes | Yes (AFC + app sandbox) | Yes | — | Planned (WDA) |
| Android | adb (AndroidDevice) |
Yes | Yes | — | Yes | Yes (AndroidUIAuto) |
| Windows | PowerShell (WindowsDevice) |
Partial | — | — | — | Planned |
macOS and HarmonyOS are not implemented yet.
Requirements
- Python >= 3.9
- Platform CLI tools on
PATH(or configured via environment variables below):- iOS (go-ios):
ios - iOS (pymobiledevice3):
pymobiledevice3(default:/opt/ios3/bin/pymobiledevice3on Unix,~/ios3/bin/pymobiledevice3.exeon Windows) - Android:
adb
- iOS (go-ios):
Python packages pymobiledevice3 and uiautomator2 are installed automatically with the project (see Install). IOSDevice3 uses the pymobiledevice3 Python library for Documents sandbox access (documents_*); other iOS operations go through the CLI.
Install
uv sync
# or, with dev dependencies
uv sync --group dev
Quick start
Create a device bound to a single UDID or serial, then call lifecycle methods:
from pathlib import Path
from idevice.device import Platform, create_device
# iOS via go-ios
device = create_device(Platform.IOS, device_id="00008030-001A…")
# iOS via pymobiledevice3 (iOS 17+ tunnel support)
device = create_device(Platform.IOS3, device_id="00008030-001A…")
# Android via adb
device = create_device(Platform.ANDROID, device_id="emulator-5554")
device.install(Path("MyApp.ipa"), app_id="com.example.app")
device.launch_app("com.example.app")
device.is_installed("com.example.app")
device.stop_app("com.example.app")
device.uninstall("com.example.app")
Android swipe (via adb shell input swipe):
device.swipe(100, 800, 100, 200, duration_ms=300)
iOS Documents sandbox (IOSDevice3 only — requires file-sharing entitlements):
device.documents_push("com.example.app", Path("log.txt"), "Logs/log.txt")
device.documents_exists("com.example.app", "Logs/log.txt")
device.documents_ls("com.example.app", "Logs")
device.documents_pull("com.example.app", "Logs", Path("out/Logs"))
UI automation (Android only today):
from idevice.uiauto import create_uiauto
uiauto = create_uiauto(Platform.ANDROID, device_id="emulator-5554")
uiauto.swipe(100, 800, 100, 200)
uiauto.dismiss_post_install_dialogs(timeout=30)
Examples
Runnable scripts under examples/ auto-detect the first connected device when no ID is passed:
# Android: launch, push/pull, swipe (optional --apk / --package)
uv run python examples/android_device.py
# iOS (pymobiledevice3): lifecycle, AFC, app sandbox, Documents API
uv run python examples/ios3_device.py
# Install an IPA and exercise sandbox file transfer
uv run python examples/ios3_device.py \
--ipa path/to/app.ipa \
--app-id com.example.app \
--sandbox-app-id com.example.app
See the module docstrings in each example for prerequisites (Developer Mode, iOS 17+ tunnel, USB debugging, etc.).
API overview
DeviceBase
Every platform implementation shares the same interface:
install(package_path, app_id=None)— install.ipa/.apkand optionally record bundle id → file nameuninstall(app_id)/is_installed(app_id)/get_installed_pkg_name(app_id)launch_app(app_id)/stop_app(app_id)push(local, remote, app_id=None, documents_only=False)/pull(remote, local, app_id=None, documents_only=True)— host ↔ device file transferls(remote, app_id=None, recursive=False)— list a remote directory on the devicedocuments_exists(app_id, remote)/documents_ls(app_id, remote)/documents_push(app_id, local, remote)/documents_pull(app_id, remote, local)— app Documents sandbox (implemented onIOSDevice3; other platforms raiseNotImplementedError)swipe(x1, y1, x2, y2, duration_ms=300)— touch gesture (Android implemented; iOS/Windows raiseNotImplementedError)host_is_running()— whether WebDriverAgent / UIAutomator2 host process is up
Use create_device(Platform, device_id=…) or construct IOSDevice, IOSDevice3, AndroidDevice, or WindowsDevice directly.
UIAutoBase
Higher-level UI helpers built on top of device tooling. Currently only AndroidUIAuto is available (swipe, dismiss_post_install_dialogs, hierarchy access).
iOS backends
IOSDevice (go-ios) — lightweight CLI wrapper around go-ios for install, launch, and AFC transfers.
IOSDevice3 (pymobiledevice3) — uses pymobiledevice3 services:
- App install/uninstall/list via
apps - Process control via
developer dvt launch/pkill - File transfer via
afc push/pullorapps push/pull(app sandbox, with optional--documents) - Documents sandbox via the pymobiledevice3 Python library (House Arrest AFC):
documents_exists,documents_ls,documents_push,documents_pull - Developer-mode commands require a mounted DeveloperDiskImage; on iOS 17+ an active tunnel is required (
pymobiledevice3 remote start-tunnel)
Choose Platform.IOS or Platform.IOS3 depending on which CLI you have deployed.
Configuration
Environment variables override default binary paths:
| Variable | Default | Used by |
|---|---|---|
IDEVICE_IOS_BINARY |
ios |
IOSDevice |
IDEVICE_IOS3_BINARY |
/opt/ios3/bin/pymobiledevice3 (Unix) / ~/ios3/bin/pymobiledevice3.exe (Windows) |
IOSDevice3 |
IDEVICE_ADB_BINARY |
adb |
AndroidDevice, AndroidUIAuto |
IDEVICE_POWERSHELL_BINARY |
powershell |
WindowsDevice |
User data (e.g. installed-app cache) is stored under ~/.idevice by default.
Testing
Unit tests run without a connected device:
uv run pytest
Integration tests under tests/device/ require a physical iOS device and pymobiledevice3. They are excluded by default; run with:
export IDEVICE_IOS3_UDID="00008030-001A…"
uv run pytest -m integration tests/device/
See tests/device/conftest.py for optional variables (IDEVICE_IOS3_TEST_IPA, sandbox push/pull settings, etc.).
Development
uv run ruff check src tests
uv run pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file idevice-0.2.0.tar.gz.
File metadata
- Download URL: idevice-0.2.0.tar.gz
- Upload date:
- Size: 173.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
199b23c0992b7a519f24f63f64c84f8aceb7df199afb0c0cc169100538362bec
|
|
| MD5 |
1ac1b4d089c0838b728cec68bb84cefe
|
|
| BLAKE2b-256 |
a48aeb5e4f129e8ef2672f0db8cc3979a4deaf17e3c12c408b2ced9138b28d4d
|
Provenance
The following attestation bundles were made for idevice-0.2.0.tar.gz:
Publisher:
workflow.yml on nzcv/idevice
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
idevice-0.2.0.tar.gz -
Subject digest:
199b23c0992b7a519f24f63f64c84f8aceb7df199afb0c0cc169100538362bec - Sigstore transparency entry: 1701817585
- Sigstore integration time:
-
Permalink:
nzcv/idevice@85b62ed69ccbd78b0e67267d664685a5b1a1953f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/nzcv
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@85b62ed69ccbd78b0e67267d664685a5b1a1953f -
Trigger Event:
push
-
Statement type:
File details
Details for the file idevice-0.2.0-py3-none-any.whl.
File metadata
- Download URL: idevice-0.2.0-py3-none-any.whl
- Upload date:
- Size: 30.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10554f381ddcd610d084899566a9c9802713ebe1ec76a90c53551ccf7100cad0
|
|
| MD5 |
2bd95fd96a17b71c8a8a0f88f35f7f3a
|
|
| BLAKE2b-256 |
358ccb2351dd9ba53043ff645831a880620078b44c4bafe95d3f4c327366f436
|
Provenance
The following attestation bundles were made for idevice-0.2.0-py3-none-any.whl:
Publisher:
workflow.yml on nzcv/idevice
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
idevice-0.2.0-py3-none-any.whl -
Subject digest:
10554f381ddcd610d084899566a9c9802713ebe1ec76a90c53551ccf7100cad0 - Sigstore transparency entry: 1701817633
- Sigstore integration time:
-
Permalink:
nzcv/idevice@85b62ed69ccbd78b0e67267d664685a5b1a1953f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/nzcv
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@85b62ed69ccbd78b0e67267d664685a5b1a1953f -
Trigger Event:
push
-
Statement type: