Write the mobile flow once, point it at Android and iOS
A mobile step names a control: the profile tab, the Sign in button. Turning that into the gesture a platform actually has is the execution kernel's job, not the author's. agent-qa decides each action from what is on the device at that moment and hands it to Appium to perform, so one flow covers an Android build and an iOS build.
A step names a control, never an event
Read a mobile step for what it does not say. It does not say tap, long press, or swipe. It names the control the user is reaching for, and working out the gesture that reaches it on this platform happens at run time. A click on a web target is a tap on a phone, and the author writes neither word.
Appium is the execution kernel underneath, and a kernel is not a code generator. No test script is produced. Nothing is replayed from a recording. The agent decides on an action from what it can currently see, hands it over, and Appium performs it. That is why one flow survives being pointed at a platform it was not written on.
The target changes, the test does not
An Android target names an app package, and usually the activity to launch. An iOS target names a bundle identifier. That is the difference between the two, and nothing else about how the test is written changes.
Only one line of the file below is platform-specific: the target. Point it at the Android target and Appium drives UiAutomator2. Point it at the iOS target and it drives XCUITest. The steps, the assertions, and everything the run remembers are untouched by that choice, so a flow that reads well on Android reads the same on iOS.
test-id: t_login-mobile
name: Sign in on the mobile app
target: shop-app-android
steps:
- Launch the app.
- Dismiss the onboarding carousel if it appears.
- Open the profile tab and choose "Sign in".
- Enter the email "{{env:TEST_EMAIL}}" and password "{{env:TEST_PASSWORD}}".
- Submit the form.
- Verify the profile tab shows the account's display name.App state and device are settings, not steps
A native run has to say what happens to the installed app. Reset gives the run a clean install. Preserve keeps whatever the last run left behind, caches and preferences included. agent-qa refuses to run a native mobile test that leaves the choice out, and the choice can be made once for the workspace, once for a suite, or per test.
Where the run lands is a device profile: a local Android emulator, an iOS simulator on your own machine, or a remote device you never have to hold. The profile is named in the file, and the command line can override it for a single run, so moving a flow onto different hardware never edits the flow. Steps, timings, artifacts, and anything learned are stored against the test, never against the platform that happened to run it.
# initialize a workspace
npx agent-qa init
# run a test
npx agent-qa run tests/checkout-smoke.yaml
# inspect runs in the local dashboard
agent-qa dashboard --port 3470 --openFrequently asked questions
Can one agent-qa test run on both Android and iOS?
Yes. The steps name controls and the target names the build, so moving between platforms is a target change. An Android target carries an app package, an iOS target carries a bundle identifier, and Appium drives UiAutomator2 on the first and XCUITest on the second. The steps stay exactly as written.
Does agent-qa generate Appium code?
No. Appium is an execution kernel here, not a code generator. agent-qa decides on an action from what is on the device and asks Appium to perform it, one action at a time. No test script is produced, so there is no generated mobile code in your repository to review or maintain.
How is this different from recording a flow on a device?
A recording captures one pass through the app and plays it back. agent-qa plays nothing back. Every action is chosen during the run from the screen in front of it, which is why the same flow can be pointed at a platform whose screens were never recorded.
Which devices can a mobile run land on?
A device profile decides: a local Android emulator, an iOS simulator on your own machine, or a remote device. The profile is selected in the test file, and the command line can override it for a single run, so the same file can be pointed at different hardware.
Does a mobile test have to declare app state?
Yes, for native Android and iOS runs. Reset gives the run a clean install, preserve keeps what the last run left behind, and the runner rejects a native mobile test that says neither. Set it once for the workspace, once for a suite, or per test when flows need different behavior. Web auth state is a separate mechanism, and native runs do not use it.