appium-pytest-kit 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. appium_pytest_kit-0.1.0/PKG-INFO +372 -0
  2. appium_pytest_kit-0.1.0/README.md +344 -0
  3. appium_pytest_kit-0.1.0/pyproject.toml +75 -0
  4. appium_pytest_kit-0.1.0/setup.cfg +4 -0
  5. appium_pytest_kit-0.1.0/src/appium_pytest_kit/__init__.py +37 -0
  6. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_internal/__init__.py +4 -0
  7. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_internal/device_resolver.py +240 -0
  8. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_internal/diagnostics.py +46 -0
  9. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_internal/reporting.py +45 -0
  10. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_internal/server.py +77 -0
  11. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_internal/video.py +50 -0
  12. appium_pytest_kit-0.1.0/src/appium_pytest_kit/_version.py +11 -0
  13. appium_pytest_kit-0.1.0/src/appium_pytest_kit/actions.py +141 -0
  14. appium_pytest_kit-0.1.0/src/appium_pytest_kit/cli.py +234 -0
  15. appium_pytest_kit-0.1.0/src/appium_pytest_kit/driver.py +93 -0
  16. appium_pytest_kit-0.1.0/src/appium_pytest_kit/errors.py +64 -0
  17. appium_pytest_kit-0.1.0/src/appium_pytest_kit/hooks.py +36 -0
  18. appium_pytest_kit-0.1.0/src/appium_pytest_kit/interfaces.py +30 -0
  19. appium_pytest_kit-0.1.0/src/appium_pytest_kit/py.typed +0 -0
  20. appium_pytest_kit-0.1.0/src/appium_pytest_kit/pytest_plugin.py +339 -0
  21. appium_pytest_kit-0.1.0/src/appium_pytest_kit/settings.py +131 -0
  22. appium_pytest_kit-0.1.0/src/appium_pytest_kit/waits.py +157 -0
  23. appium_pytest_kit-0.1.0/src/appium_pytest_kit.egg-info/PKG-INFO +372 -0
  24. appium_pytest_kit-0.1.0/src/appium_pytest_kit.egg-info/SOURCES.txt +26 -0
  25. appium_pytest_kit-0.1.0/src/appium_pytest_kit.egg-info/dependency_links.txt +1 -0
  26. appium_pytest_kit-0.1.0/src/appium_pytest_kit.egg-info/entry_points.txt +5 -0
  27. appium_pytest_kit-0.1.0/src/appium_pytest_kit.egg-info/requires.txt +7 -0
  28. appium_pytest_kit-0.1.0/src/appium_pytest_kit.egg-info/top_level.txt +1 -0
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.4
2
+ Name: appium-pytest-kit
3
+ Version: 0.1.0
4
+ Summary: Reusable Appium 2.x + pytest mobile test framework
5
+ Author: appium-pytest-kit contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/gianlucasoare/appium-pytest-kit
8
+ Project-URL: Documentation, https://github.com/gianlucasoare/appium-pytest-kit#readme
9
+ Project-URL: Repository, https://github.com/gianlucasoare/appium-pytest-kit.git
10
+ Keywords: appium,pytest,mobile,automation,framework
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Framework :: Pytest
19
+ Classifier: Topic :: Software Development :: Testing
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: Appium-Python-Client>=4.0.0
23
+ Requires-Dist: pydantic-settings>=2.3.0
24
+ Requires-Dist: pytest>=8.2.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: ruff>=0.9.0; extra == "dev"
27
+ Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
28
+
29
+ # appium-pytest-kit
30
+
31
+ `appium-pytest-kit` is a reusable Appium 2.x + pytest framework library for Python 3.11+.
32
+
33
+ - `pip install appium-pytest-kit` (or install from GitHub — see below)
34
+ - `appium-pytest-kit-init` to bootstrap configuration, or `--framework` to scaffold a full project
35
+ - Write tests immediately with built-in fixtures and zero boilerplate
36
+
37
+ **Full documentation:** [DOCUMENTATION.md](./DOCUMENTATION.md)
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ ### From PyPI (once published)
44
+
45
+ ```bash
46
+ pip install appium-pytest-kit
47
+ ```
48
+
49
+ ### From GitHub
50
+
51
+ ```bash
52
+ # latest main branch
53
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git
54
+
55
+ # specific branch
56
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git@main
57
+
58
+ # specific tag
59
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git@v0.1.0
60
+ ```
61
+
62
+ ### Local clone (editable, for development)
63
+
64
+ ```bash
65
+ git clone https://github.com/gianlucasoare/appium-pytest-kit.git
66
+ cd appium-pytest-kit
67
+ pip install -e ".[dev]"
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Quickstart
73
+
74
+ ```bash
75
+ python -m venv .venv
76
+ source .venv/bin/activate
77
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git
78
+ appium-pytest-kit-init # creates .env with starter config
79
+ # or scaffold a full project:
80
+ appium-pytest-kit-init --framework --root my-project
81
+ pytest -q
82
+ ```
83
+
84
+ Edit `.env` with your device and app details, then write tests.
85
+
86
+ ---
87
+
88
+ ## Step-by-step: test a real app in 5 minutes
89
+
90
+ This example tests the Android Calculator on an emulator. See [DOCUMENTATION.md](./DOCUMENTATION.md) for the full iOS walkthrough and all options.
91
+
92
+ ### 1. Start Appium and an emulator
93
+
94
+ ```bash
95
+ appium &
96
+ emulator -avd Pixel_7_API_33 &
97
+ adb devices # confirm emulator-5554 is listed
98
+ ```
99
+
100
+ ### 2. Configure `.env`
101
+
102
+ ```env
103
+ APP_PLATFORM=android
104
+ APP_APPIUM_URL=http://127.0.0.1:4723
105
+ APP_DEVICE_NAME=emulator-5554
106
+ APP_PLATFORM_VERSION=13
107
+ APP_APP_PACKAGE=com.google.android.calculator
108
+ APP_APP_ACTIVITY=com.android.calculator2.Calculator
109
+ APP_NO_RESET=true
110
+ ```
111
+
112
+ ### 3. Write a test
113
+
114
+ ```python
115
+ # tests/test_calculator.py
116
+ import pytest
117
+ from appium.webdriver.common.appiumby import AppiumBy
118
+
119
+ BTN_2 = (AppiumBy.ACCESSIBILITY_ID, "2")
120
+ BTN_PLUS = (AppiumBy.ACCESSIBILITY_ID, "plus")
121
+ BTN_3 = (AppiumBy.ACCESSIBILITY_ID, "3")
122
+ BTN_EQUALS = (AppiumBy.ACCESSIBILITY_ID, "equals")
123
+ RESULT = (AppiumBy.RESOURCE_ID, "com.google.android.calculator:id/result_final")
124
+
125
+
126
+ @pytest.mark.integration
127
+ def test_addition(actions):
128
+ actions.tap(BTN_2)
129
+ actions.tap(BTN_PLUS)
130
+ actions.tap(BTN_3)
131
+ actions.tap(BTN_EQUALS)
132
+ assert actions.text(RESULT) == "5"
133
+ ```
134
+
135
+ ### 4. Run it
136
+
137
+ ```bash
138
+ pytest -m integration -v
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Built-in fixtures
144
+
145
+ | Fixture | Scope | Description |
146
+ |---|---|---|
147
+ | `settings` | session | Resolved `AppiumPytestKitSettings` — access any config field |
148
+ | `appium_server` | session | Server URL and whether it is framework-managed |
149
+ | `driver` | function | Live `appium.webdriver.Remote`, quit automatically after each test |
150
+ | `waiter` | function | Explicit waits with `WaitTimeoutError` on timeout |
151
+ | `actions` | function | High-level UI helpers: `tap`, `type_text`, `text`, `exists`, `swipe`, and more |
152
+
153
+ ---
154
+
155
+ ## Session modes
156
+
157
+ Control driver lifecycle per test or across the whole session:
158
+
159
+ ```env
160
+ APP_SESSION_MODE=clean # default: fresh driver per test
161
+ APP_SESSION_MODE=clean-session # shared driver, app reset between tests
162
+ APP_SESSION_MODE=debug # shared driver, no reset (fast local debugging)
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Device resolution (3-tier priority)
168
+
169
+ 1. **Explicit** — `APP_DEVICE_NAME` / `APP_UDID` set in `.env` or CLI
170
+ 2. **Profile** — `APP_DEVICE_PROFILE=pixel7` resolved from `data/devices.yaml`
171
+ 3. **Auto-detect** — `adb devices` (Android) or `xcrun simctl` / `xctrace` (iOS)
172
+
173
+ ```bash
174
+ # Use a named profile from data/devices.yaml
175
+ pytest --app-device-profile pixel7
176
+
177
+ # Auto-detect (no device settings needed)
178
+ pytest
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Failure diagnostics
184
+
185
+ On test failure the framework automatically captures:
186
+ - **Screenshot** → `artifacts/screenshots/<test_id>.png`
187
+ - **Page source** → `artifacts/pagesource/<test_id>.xml`
188
+ - **Video** (if policy allows) → `artifacts/videos/<test_id>.mp4`
189
+
190
+ ```env
191
+ APP_VIDEO_POLICY=never # default
192
+ APP_VIDEO_POLICY=failed # record and save only on failure
193
+ APP_VIDEO_POLICY=always # record every test
194
+ APP_ARTIFACTS_DIR=artifacts
195
+ ```
196
+
197
+ Allure attachments are added automatically when `allure-pytest` is installed.
198
+
199
+ ---
200
+
201
+ ## Configuration
202
+
203
+ Settings are loaded from `.env` → environment variables → CLI flags (highest wins).
204
+
205
+ ```bash
206
+ pytest --app-platform ios
207
+ pytest --app-device-name "Pixel 7" --app-platform-version 13
208
+ pytest --appium-url http://192.168.1.10:4723
209
+ pytest --app-app-package com.example.app --app-app-activity .MainActivity
210
+ pytest --app-session-mode clean-session
211
+ pytest --app-device-profile pixel7
212
+ pytest --app-video-policy failed
213
+ pytest --app-is-simulator
214
+ pytest --app-capabilities-json '{"autoGrantPermissions": true}'
215
+ pytest --app-manage-appium-server # start Appium automatically
216
+ pytest --app-reporting-enabled # write artifacts/appium-pytest-kit/summary.json
217
+ ```
218
+
219
+ See [DOCUMENTATION.md § Configuration](./DOCUMENTATION.md#5-configuration) for the full settings table.
220
+
221
+ ---
222
+
223
+ ## Expanded waits
224
+
225
+ ```python
226
+ waiter.for_clickable(locator) # wait for element to be tappable
227
+ waiter.for_invisibility(locator) # wait for element to disappear
228
+ waiter.for_text_contains(locator, "partial text") # wait for text substring
229
+ waiter.for_text_equals(locator, "exact text") # wait for exact text match
230
+ waiter.for_all_visible([loc1, loc2, loc3]) # wait for all elements to appear
231
+ waiter.for_any_visible([loc1, loc2]) # wait for first visible element
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Expanded actions
237
+
238
+ ```python
239
+ actions.tap_if_present(locator) # tap only if visible, returns bool
240
+ actions.clear(locator) # clear a text field
241
+ actions.swipe(sx, sy, ex, ey) # W3C Pointer swipe gesture
242
+ actions.scroll_down() # swipe up on screen center
243
+ actions.scroll_up() # swipe down on screen center
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Extension hooks
249
+
250
+ Implement these in your `conftest.py` to customise behaviour without touching the framework:
251
+
252
+ ```python
253
+ # conftest.py
254
+
255
+ def pytest_appium_pytest_kit_capabilities(capabilities, settings):
256
+ """Add extra capabilities before each driver session."""
257
+ return {"autoGrantPermissions": True, "language": "en"}
258
+
259
+
260
+ def pytest_appium_pytest_kit_configure_settings(settings):
261
+ """Replace settings at session start."""
262
+ return settings.model_copy(update={"implicit_wait": 2.0})
263
+
264
+
265
+ def pytest_appium_pytest_kit_driver_created(driver, settings):
266
+ """Run setup immediately after each driver is created."""
267
+ driver.orientation = "PORTRAIT"
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Project scaffolding
273
+
274
+ Generate a full project structure in one command:
275
+
276
+ ```bash
277
+ appium-pytest-kit-init --framework --root my-project
278
+ ```
279
+
280
+ Creates:
281
+ ```
282
+ my-project/
283
+ ├── data/devices.yaml # device profiles
284
+ ├── pages/
285
+ │ ├── base_page.py # BasePage composition class
286
+ │ └── example_page.py # starter page object
287
+ ├── flows/ # reusable multi-step flows
288
+ ├── tests/
289
+ │ ├── android/test_smoke.py
290
+ │ └── ios/test_smoke.py
291
+ ├── conftest.py
292
+ ├── pytest.ini
293
+ └── .env.example
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Public API
299
+
300
+ Top-level imports (stable):
301
+
302
+ ```python
303
+ from appium_pytest_kit import (
304
+ AppiumPytestKitSettings,
305
+ AppiumPytestKitError,
306
+ ConfigurationError,
307
+ DeviceResolutionError,
308
+ LaunchValidationError,
309
+ WaitTimeoutError,
310
+ ActionError,
311
+ DriverCreationError,
312
+ DeviceInfo,
313
+ DriverConfig,
314
+ MobileActions,
315
+ Waiter,
316
+ build_driver_config,
317
+ create_driver,
318
+ load_settings,
319
+ apply_cli_overrides,
320
+ )
321
+ ```
322
+
323
+ Stable public modules (direct import):
324
+ - `appium_pytest_kit.settings`
325
+ - `appium_pytest_kit.driver`
326
+ - `appium_pytest_kit.waits`
327
+ - `appium_pytest_kit.actions`
328
+ - `appium_pytest_kit.errors`
329
+ - `appium_pytest_kit.interfaces` — `CapabilitiesAdapter` protocol for custom adapters
330
+
331
+ Private/internal modules (no compatibility guarantee):
332
+ - `appium_pytest_kit._internal.*`
333
+
334
+ ---
335
+
336
+ ## Fixture lifecycle
337
+
338
+ ```mermaid
339
+ flowchart TD
340
+ A["pytest start"] --> B["load defaults + .env + env vars"]
341
+ B --> C["apply --app-* CLI overrides"]
342
+ C --> D["settings fixture (session)"]
343
+ D --> E{"APP_MANAGE_APPIUM_SERVER"}
344
+ E -->|"true"| F["start local Appium server"]
345
+ E -->|"false"| G["use APP_APPIUM_URL"]
346
+ F --> H["appium_server fixture"]
347
+ G --> H
348
+ H --> I{"session_mode"}
349
+ I -->|"clean-session / debug"| J["_driver_shared (session)"]
350
+ I -->|"clean"| K["driver per test"]
351
+ J --> K
352
+ K --> L["waiter / actions fixtures"]
353
+ K --> M["test executes"]
354
+ M --> N{"failed?"}
355
+ N -->|"yes"| O["capture screenshot + page source"]
356
+ N --> P["video stop (per policy)"]
357
+ O --> P
358
+ P --> Q["driver.quit() if clean mode"]
359
+ Q --> R["optional report summary flush"]
360
+ R --> S["optional server stop"]
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Local development
366
+
367
+ ```bash
368
+ pip install -e ".[dev]"
369
+ ruff check .
370
+ pytest -q
371
+ pytest --collect-only examples/basic/tests -q
372
+ ```
@@ -0,0 +1,344 @@
1
+ # appium-pytest-kit
2
+
3
+ `appium-pytest-kit` is a reusable Appium 2.x + pytest framework library for Python 3.11+.
4
+
5
+ - `pip install appium-pytest-kit` (or install from GitHub — see below)
6
+ - `appium-pytest-kit-init` to bootstrap configuration, or `--framework` to scaffold a full project
7
+ - Write tests immediately with built-in fixtures and zero boilerplate
8
+
9
+ **Full documentation:** [DOCUMENTATION.md](./DOCUMENTATION.md)
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ### From PyPI (once published)
16
+
17
+ ```bash
18
+ pip install appium-pytest-kit
19
+ ```
20
+
21
+ ### From GitHub
22
+
23
+ ```bash
24
+ # latest main branch
25
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git
26
+
27
+ # specific branch
28
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git@main
29
+
30
+ # specific tag
31
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git@v0.1.0
32
+ ```
33
+
34
+ ### Local clone (editable, for development)
35
+
36
+ ```bash
37
+ git clone https://github.com/gianlucasoare/appium-pytest-kit.git
38
+ cd appium-pytest-kit
39
+ pip install -e ".[dev]"
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Quickstart
45
+
46
+ ```bash
47
+ python -m venv .venv
48
+ source .venv/bin/activate
49
+ pip install git+https://github.com/gianlucasoare/appium-pytest-kit.git
50
+ appium-pytest-kit-init # creates .env with starter config
51
+ # or scaffold a full project:
52
+ appium-pytest-kit-init --framework --root my-project
53
+ pytest -q
54
+ ```
55
+
56
+ Edit `.env` with your device and app details, then write tests.
57
+
58
+ ---
59
+
60
+ ## Step-by-step: test a real app in 5 minutes
61
+
62
+ This example tests the Android Calculator on an emulator. See [DOCUMENTATION.md](./DOCUMENTATION.md) for the full iOS walkthrough and all options.
63
+
64
+ ### 1. Start Appium and an emulator
65
+
66
+ ```bash
67
+ appium &
68
+ emulator -avd Pixel_7_API_33 &
69
+ adb devices # confirm emulator-5554 is listed
70
+ ```
71
+
72
+ ### 2. Configure `.env`
73
+
74
+ ```env
75
+ APP_PLATFORM=android
76
+ APP_APPIUM_URL=http://127.0.0.1:4723
77
+ APP_DEVICE_NAME=emulator-5554
78
+ APP_PLATFORM_VERSION=13
79
+ APP_APP_PACKAGE=com.google.android.calculator
80
+ APP_APP_ACTIVITY=com.android.calculator2.Calculator
81
+ APP_NO_RESET=true
82
+ ```
83
+
84
+ ### 3. Write a test
85
+
86
+ ```python
87
+ # tests/test_calculator.py
88
+ import pytest
89
+ from appium.webdriver.common.appiumby import AppiumBy
90
+
91
+ BTN_2 = (AppiumBy.ACCESSIBILITY_ID, "2")
92
+ BTN_PLUS = (AppiumBy.ACCESSIBILITY_ID, "plus")
93
+ BTN_3 = (AppiumBy.ACCESSIBILITY_ID, "3")
94
+ BTN_EQUALS = (AppiumBy.ACCESSIBILITY_ID, "equals")
95
+ RESULT = (AppiumBy.RESOURCE_ID, "com.google.android.calculator:id/result_final")
96
+
97
+
98
+ @pytest.mark.integration
99
+ def test_addition(actions):
100
+ actions.tap(BTN_2)
101
+ actions.tap(BTN_PLUS)
102
+ actions.tap(BTN_3)
103
+ actions.tap(BTN_EQUALS)
104
+ assert actions.text(RESULT) == "5"
105
+ ```
106
+
107
+ ### 4. Run it
108
+
109
+ ```bash
110
+ pytest -m integration -v
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Built-in fixtures
116
+
117
+ | Fixture | Scope | Description |
118
+ |---|---|---|
119
+ | `settings` | session | Resolved `AppiumPytestKitSettings` — access any config field |
120
+ | `appium_server` | session | Server URL and whether it is framework-managed |
121
+ | `driver` | function | Live `appium.webdriver.Remote`, quit automatically after each test |
122
+ | `waiter` | function | Explicit waits with `WaitTimeoutError` on timeout |
123
+ | `actions` | function | High-level UI helpers: `tap`, `type_text`, `text`, `exists`, `swipe`, and more |
124
+
125
+ ---
126
+
127
+ ## Session modes
128
+
129
+ Control driver lifecycle per test or across the whole session:
130
+
131
+ ```env
132
+ APP_SESSION_MODE=clean # default: fresh driver per test
133
+ APP_SESSION_MODE=clean-session # shared driver, app reset between tests
134
+ APP_SESSION_MODE=debug # shared driver, no reset (fast local debugging)
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Device resolution (3-tier priority)
140
+
141
+ 1. **Explicit** — `APP_DEVICE_NAME` / `APP_UDID` set in `.env` or CLI
142
+ 2. **Profile** — `APP_DEVICE_PROFILE=pixel7` resolved from `data/devices.yaml`
143
+ 3. **Auto-detect** — `adb devices` (Android) or `xcrun simctl` / `xctrace` (iOS)
144
+
145
+ ```bash
146
+ # Use a named profile from data/devices.yaml
147
+ pytest --app-device-profile pixel7
148
+
149
+ # Auto-detect (no device settings needed)
150
+ pytest
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Failure diagnostics
156
+
157
+ On test failure the framework automatically captures:
158
+ - **Screenshot** → `artifacts/screenshots/<test_id>.png`
159
+ - **Page source** → `artifacts/pagesource/<test_id>.xml`
160
+ - **Video** (if policy allows) → `artifacts/videos/<test_id>.mp4`
161
+
162
+ ```env
163
+ APP_VIDEO_POLICY=never # default
164
+ APP_VIDEO_POLICY=failed # record and save only on failure
165
+ APP_VIDEO_POLICY=always # record every test
166
+ APP_ARTIFACTS_DIR=artifacts
167
+ ```
168
+
169
+ Allure attachments are added automatically when `allure-pytest` is installed.
170
+
171
+ ---
172
+
173
+ ## Configuration
174
+
175
+ Settings are loaded from `.env` → environment variables → CLI flags (highest wins).
176
+
177
+ ```bash
178
+ pytest --app-platform ios
179
+ pytest --app-device-name "Pixel 7" --app-platform-version 13
180
+ pytest --appium-url http://192.168.1.10:4723
181
+ pytest --app-app-package com.example.app --app-app-activity .MainActivity
182
+ pytest --app-session-mode clean-session
183
+ pytest --app-device-profile pixel7
184
+ pytest --app-video-policy failed
185
+ pytest --app-is-simulator
186
+ pytest --app-capabilities-json '{"autoGrantPermissions": true}'
187
+ pytest --app-manage-appium-server # start Appium automatically
188
+ pytest --app-reporting-enabled # write artifacts/appium-pytest-kit/summary.json
189
+ ```
190
+
191
+ See [DOCUMENTATION.md § Configuration](./DOCUMENTATION.md#5-configuration) for the full settings table.
192
+
193
+ ---
194
+
195
+ ## Expanded waits
196
+
197
+ ```python
198
+ waiter.for_clickable(locator) # wait for element to be tappable
199
+ waiter.for_invisibility(locator) # wait for element to disappear
200
+ waiter.for_text_contains(locator, "partial text") # wait for text substring
201
+ waiter.for_text_equals(locator, "exact text") # wait for exact text match
202
+ waiter.for_all_visible([loc1, loc2, loc3]) # wait for all elements to appear
203
+ waiter.for_any_visible([loc1, loc2]) # wait for first visible element
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Expanded actions
209
+
210
+ ```python
211
+ actions.tap_if_present(locator) # tap only if visible, returns bool
212
+ actions.clear(locator) # clear a text field
213
+ actions.swipe(sx, sy, ex, ey) # W3C Pointer swipe gesture
214
+ actions.scroll_down() # swipe up on screen center
215
+ actions.scroll_up() # swipe down on screen center
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Extension hooks
221
+
222
+ Implement these in your `conftest.py` to customise behaviour without touching the framework:
223
+
224
+ ```python
225
+ # conftest.py
226
+
227
+ def pytest_appium_pytest_kit_capabilities(capabilities, settings):
228
+ """Add extra capabilities before each driver session."""
229
+ return {"autoGrantPermissions": True, "language": "en"}
230
+
231
+
232
+ def pytest_appium_pytest_kit_configure_settings(settings):
233
+ """Replace settings at session start."""
234
+ return settings.model_copy(update={"implicit_wait": 2.0})
235
+
236
+
237
+ def pytest_appium_pytest_kit_driver_created(driver, settings):
238
+ """Run setup immediately after each driver is created."""
239
+ driver.orientation = "PORTRAIT"
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Project scaffolding
245
+
246
+ Generate a full project structure in one command:
247
+
248
+ ```bash
249
+ appium-pytest-kit-init --framework --root my-project
250
+ ```
251
+
252
+ Creates:
253
+ ```
254
+ my-project/
255
+ ├── data/devices.yaml # device profiles
256
+ ├── pages/
257
+ │ ├── base_page.py # BasePage composition class
258
+ │ └── example_page.py # starter page object
259
+ ├── flows/ # reusable multi-step flows
260
+ ├── tests/
261
+ │ ├── android/test_smoke.py
262
+ │ └── ios/test_smoke.py
263
+ ├── conftest.py
264
+ ├── pytest.ini
265
+ └── .env.example
266
+ ```
267
+
268
+ ---
269
+
270
+ ## Public API
271
+
272
+ Top-level imports (stable):
273
+
274
+ ```python
275
+ from appium_pytest_kit import (
276
+ AppiumPytestKitSettings,
277
+ AppiumPytestKitError,
278
+ ConfigurationError,
279
+ DeviceResolutionError,
280
+ LaunchValidationError,
281
+ WaitTimeoutError,
282
+ ActionError,
283
+ DriverCreationError,
284
+ DeviceInfo,
285
+ DriverConfig,
286
+ MobileActions,
287
+ Waiter,
288
+ build_driver_config,
289
+ create_driver,
290
+ load_settings,
291
+ apply_cli_overrides,
292
+ )
293
+ ```
294
+
295
+ Stable public modules (direct import):
296
+ - `appium_pytest_kit.settings`
297
+ - `appium_pytest_kit.driver`
298
+ - `appium_pytest_kit.waits`
299
+ - `appium_pytest_kit.actions`
300
+ - `appium_pytest_kit.errors`
301
+ - `appium_pytest_kit.interfaces` — `CapabilitiesAdapter` protocol for custom adapters
302
+
303
+ Private/internal modules (no compatibility guarantee):
304
+ - `appium_pytest_kit._internal.*`
305
+
306
+ ---
307
+
308
+ ## Fixture lifecycle
309
+
310
+ ```mermaid
311
+ flowchart TD
312
+ A["pytest start"] --> B["load defaults + .env + env vars"]
313
+ B --> C["apply --app-* CLI overrides"]
314
+ C --> D["settings fixture (session)"]
315
+ D --> E{"APP_MANAGE_APPIUM_SERVER"}
316
+ E -->|"true"| F["start local Appium server"]
317
+ E -->|"false"| G["use APP_APPIUM_URL"]
318
+ F --> H["appium_server fixture"]
319
+ G --> H
320
+ H --> I{"session_mode"}
321
+ I -->|"clean-session / debug"| J["_driver_shared (session)"]
322
+ I -->|"clean"| K["driver per test"]
323
+ J --> K
324
+ K --> L["waiter / actions fixtures"]
325
+ K --> M["test executes"]
326
+ M --> N{"failed?"}
327
+ N -->|"yes"| O["capture screenshot + page source"]
328
+ N --> P["video stop (per policy)"]
329
+ O --> P
330
+ P --> Q["driver.quit() if clean mode"]
331
+ Q --> R["optional report summary flush"]
332
+ R --> S["optional server stop"]
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Local development
338
+
339
+ ```bash
340
+ pip install -e ".[dev]"
341
+ ruff check .
342
+ pytest -q
343
+ pytest --collect-only examples/basic/tests -q
344
+ ```