|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Purpose |
| 6 | + |
| 7 | +Example project showing how to drive a remote Appium session on the TestingBot cloud device grid from Robot Framework to run native mobile app tests. It is intentionally small — one suite (`test.robot`) plus two Python helper libraries. |
| 8 | + |
| 9 | +## Running tests |
| 10 | + |
| 11 | +`PYTHONPATH` must include the repo root so Robot Framework can import the local Python libraries (`AppOptions.py`, `TestingBot.py`) as libraries named `AppOptions` / `TestingBot`. |
| 12 | + |
| 13 | +``` |
| 14 | +pip install -r requirements.txt |
| 15 | +export TB_KEY=<key> |
| 16 | +export TB_SECRET=<secret> |
| 17 | +PYTHONPATH=$PYTHONPATH:. robot \ |
| 18 | + --variable PLATFORM:Android \ |
| 19 | + --variable VERSION:14.0 \ |
| 20 | + --variable DEVICE:Pixel.* \ |
| 21 | + --variable APP:https://testingbot.com/appium/sample.apk \ |
| 22 | + test.robot |
| 23 | +``` |
| 24 | + |
| 25 | +Run a single test case: add `--test "Simple App Test"` (or `-t`) to the `robot` invocation. |
| 26 | + |
| 27 | +`TB_KEY` / `TB_SECRET` are read from `os.environ` inside `TestingBot.py` — **do not** pass them via `--variable` or embed them in the remote URL, or they will leak into `log.html` / `output.xml`. The four `--variable` args (`PLATFORM`, `VERSION`, `DEVICE`, `APP`) are required — the suite references them with no defaults. CI (`.github/workflows/test-python.yml`) injects `TB_KEY`/`TB_SECRET` via the job's `env:` block from GitHub secrets. |
| 28 | + |
| 29 | +## Architecture |
| 30 | + |
| 31 | +The suite is three pieces that plug together via Robot Framework's `Library` imports: |
| 32 | + |
| 33 | +- **`test.robot`** — declares `AppiumLibrary`, `AppOptions`, and `TestingBot` as libraries. `Test Setup` calls `Get App Options` to get an Appium platform-specific `*Options` object (e.g. `UiAutomator2Options` / `XCUITestOptions`), attaches W3C + Appium capabilities and a `tb:options` dict (TestingBot-specific metadata like build name) via `Call Method ... set_capability`, then hands the configured options off to `Open Testingbot App`. The suite never references credentials. |
| 34 | + |
| 35 | +- **`AppOptions.py`** — factory returning `UiAutomator2Options` / `XCUITestOptions` based on the `PLATFORM` variable. Keeping this in Python (rather than Robot keywords) is deliberate: the test needs a real Appium options *object* to call `set_capability` on. |
| 36 | + |
| 37 | +- **`TestingBot.py`** — owns all TestingBot/credential concerns. Reads `TB_KEY`/`TB_SECRET` from `os.environ`, builds a `selenium.webdriver.remote.client_config.ClientConfig` with basic auth, and creates the remote Appium driver via `appium.webdriver.Remote(...)`. It then registers the driver in the running `AppiumLibrary` instance's `_cache` — this both avoids URL-embedded credentials (which would be logged) and means subsequent AppiumLibrary keywords (`Wait Until Page Contains Element`, `Click Element`, …) just work. `Report Testingbot Status` then reaches into the running `AppiumLibrary` instance for the live `session_id` and PUTs pass/fail to `api.testingbot.com/v1/tests/<session_id>`. This only works while the app session is still open, which is why it runs *before* `Close Application` in the teardown. |
| 38 | + |
| 39 | +Note: `AppiumLibrary`'s own `Open Application` keyword also creates the driver, but only accepts capability kwargs and would require embedding credentials in the remote URL. Registering our own driver in `appium._cache` is the escape hatch that keeps credentials out of the URL and the logs. |
| 40 | + |
| 41 | +When changing capabilities or adding platform-specific flags, edit `test.robot` (capabilities) or `AppOptions.py` (options object construction) — don't try to do it purely in Robot syntax. If you need to change how the driver is created or how auth is handled, that all lives in `TestingBot.py:open_testingbot_app` — keep credentials out of `test.robot` and out of Robot variables. |
| 42 | + |
| 43 | +## Ignorable artifacts |
| 44 | + |
| 45 | +`log.html`, `report.html`, `output.xml`, `.pabotsuitenames`, and `pabot_results/` are generated by `robot`/`pabot` runs and should not be committed or treated as source. |
0 commit comments