$npx -y skills add PramodDutta/qaskills --skill appium-mobileMobile application testing skill using Appium for iOS and Android, covering device capabilities, selectors, gestures, and cross-platform testing strategies.
| 1 | # Appium Mobile Testing Skill |
| 2 | |
| 3 | You are an expert QA automation engineer specializing in mobile testing with Appium. When the user asks you to write, review, or debug Appium mobile tests, follow these detailed instructions. |
| 4 | |
| 5 | ## Core Principles |
| 6 | |
| 7 | 1. **Cross-platform design** -- Write tests that can run on both iOS and Android with minimal duplication. |
| 8 | 2. **Accessibility-first selectors** -- Use accessibility IDs as the primary selector strategy. |
| 9 | 3. **Explicit waits** -- Mobile apps have variable load times; always use explicit waits. |
| 10 | 4. **Real device preference** -- Test on real devices when possible; emulators for development. |
| 11 | 5. **App lifecycle management** -- Handle app install, launch, background, and foreground states. |
| 12 | |
| 13 | ## Project Structure (Java) |
| 14 | |
| 15 | ``` |
| 16 | src/ |
| 17 | main/java/com/example/ |
| 18 | pages/ |
| 19 | BasePage.java |
| 20 | LoginPage.java |
| 21 | HomePage.java |
| 22 | utils/ |
| 23 | DriverFactory.java |
| 24 | GestureHelper.java |
| 25 | WaitHelper.java |
| 26 | CapabilityBuilder.java |
| 27 | config/ |
| 28 | AppConfig.java |
| 29 | test/java/com/example/ |
| 30 | tests/ |
| 31 | BaseTest.java |
| 32 | LoginTest.java |
| 33 | HomeTest.java |
| 34 | data/ |
| 35 | TestDataProvider.java |
| 36 | test/resources/ |
| 37 | apps/ |
| 38 | app-debug.apk |
| 39 | app-release.ipa |
| 40 | config/ |
| 41 | android.properties |
| 42 | ios.properties |
| 43 | pom.xml |
| 44 | ``` |
| 45 | |
| 46 | ## Project Structure (TypeScript with WebdriverIO) |
| 47 | |
| 48 | ``` |
| 49 | tests/ |
| 50 | mobile/ |
| 51 | specs/ |
| 52 | login.spec.ts |
| 53 | home.spec.ts |
| 54 | pages/ |
| 55 | base.page.ts |
| 56 | login.page.ts |
| 57 | home.page.ts |
| 58 | utils/ |
| 59 | gestures.ts |
| 60 | helpers.ts |
| 61 | config/ |
| 62 | wdio.android.conf.ts |
| 63 | wdio.ios.conf.ts |
| 64 | apps/ |
| 65 | android/ |
| 66 | app-debug.apk |
| 67 | ios/ |
| 68 | app-release.ipa |
| 69 | package.json |
| 70 | ``` |
| 71 | |
| 72 | ## Desired Capabilities |
| 73 | |
| 74 | ### Android Capabilities |
| 75 | |
| 76 | ```java |
| 77 | UiAutomator2Options options = new UiAutomator2Options() |
| 78 | .setDeviceName("Pixel 6") |
| 79 | .setPlatformVersion("14") |
| 80 | .setApp(System.getProperty("user.dir") + "/apps/app-debug.apk") |
| 81 | .setAppPackage("com.example.myapp") |
| 82 | .setAppActivity("com.example.myapp.MainActivity") |
| 83 | .setAutomationName("UiAutomator2") |
| 84 | .setNoReset(false) |
| 85 | .setFullReset(false) |
| 86 | .setNewCommandTimeout(Duration.ofSeconds(300)) |
| 87 | .setAutoGrantPermissions(true); |
| 88 | |
| 89 | // For running on a real device |
| 90 | options.setUdid("emulator-5554"); |
| 91 | |
| 92 | // Performance options |
| 93 | options.setCapability("disableWindowAnimation", true); |
| 94 | options.setCapability("skipServerInstallation", false); |
| 95 | ``` |
| 96 | |
| 97 | ### iOS Capabilities |
| 98 | |
| 99 | ```java |
| 100 | XCUITestOptions options = new XCUITestOptions() |
| 101 | .setDeviceName("iPhone 15 Pro") |
| 102 | .setPlatformVersion("17.0") |
| 103 | .setApp(System.getProperty("user.dir") + "/apps/MyApp.ipa") |
| 104 | .setBundleId("com.example.myapp") |
| 105 | .setAutomationName("XCUITest") |
| 106 | .setNoReset(false) |
| 107 | .setAutoAcceptAlerts(true) |
| 108 | .setNewCommandTimeout(Duration.ofSeconds(300)); |
| 109 | |
| 110 | // For simulators |
| 111 | options.setCapability("useSimulator", true); |
| 112 | |
| 113 | // For real devices |
| 114 | options.setUdid("device-udid-here"); |
| 115 | options.setCapability("xcodeOrgId", "YOUR_TEAM_ID"); |
| 116 | options.setCapability("xcodeSigningId", "iPhone Developer"); |
| 117 | ``` |
| 118 | |
| 119 | ### WebdriverIO Configuration (TypeScript) |
| 120 | |
| 121 | ```typescript |
| 122 | // wdio.android.conf.ts |
| 123 | export const config: WebdriverIO.Config = { |
| 124 | runner: 'local', |
| 125 | port: 4723, |
| 126 | specs: ['./tests/mobile/specs/**/*.spec.ts'], |
| 127 | capabilities: [{ |
| 128 | platformName: 'Android', |
| 129 | 'appium:deviceName': 'Pixel 6', |
| 130 | 'appium:platformVersion': '14', |
| 131 | 'appium:app': './apps/android/app-debug.apk', |
| 132 | 'appium:automationName': 'UiAutomator2', |
| 133 | 'appium:noReset': false, |
| 134 | 'appium:autoGrantPermissions': true, |
| 135 | }], |
| 136 | framework: 'mocha', |
| 137 | mochaOpts: { |
| 138 | timeout: 60000, |
| 139 | }, |
| 140 | services: ['appium'], |
| 141 | }; |
| 142 | ``` |
| 143 | |
| 144 | ## Page Object Model |
| 145 | |
| 146 | ### Base Page (Java) |
| 147 | |
| 148 | ```java |
| 149 | package com.example.pages; |
| 150 | |
| 151 | import io.appium.java_client.AppiumBy; |
| 152 | import io.appium.java_client.AppiumDriver; |
| 153 | import io.appium.java_client.pagefactory.AppiumFieldDecorator; |
| 154 | import org.openqa.selenium.WebElement; |
| 155 | import org.openqa.selenium.support.PageFactory; |
| 156 | import org.openqa.selenium.support.ui.ExpectedConditions; |
| 157 | import org.openqa.selenium.support.ui.WebDriverWait; |
| 158 | |
| 159 | import java.time.Duration; |
| 160 | |
| 161 | public abstract class BasePage { |
| 162 | protected AppiumDriver driver; |
| 163 | protected WebDriverWait wait; |
| 164 | |
| 165 | public BasePage(AppiumDriver driver) { |
| 166 | this.driver = driver; |
| 167 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(15)); |
| 168 | PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(10)), this); |
| 169 | } |
| 170 | |
| 171 | protected WebElement waitForElement(String |