Who Is This Course For?
Built for Java automation engineers who can already automate web browsers using Selenium and want to extend that skill into mobile testing — automating Android and iOS apps on real devices and emulators using Appium.
Revision Classes — Java Advanced & Selenium Basics
The opening sessions of each batch cover hands-on revision of Java OOP (encapsulation, inheritance, polymorphism, abstraction), Java Collections (List, ArrayList, Stack, Map, HashMap), GitHub, and Selenium WebDriver fundamentals. The scope and pace of revision is calibrated per batch and these topics are not counted as standalone course modules.
- Appium server-client architecture — how your code talks to the phone
- How Appium extends the Selenium WebDriver protocol to mobile
- Appium vs Selenium — what's the same, what's different
- JSON Wire Protocol / W3C WebDriver protocol
UiAutomator2driver for Android automationXCUITestdriver for iOS automation
- Install
Node.jsandnpm— Appium runs on Node - Install Appium globally:
npm install -g appium - Install
appium-uiautomator2-driverfor Android - Set
ANDROID_HOMEand configurePATHfor SDK tools - Verify full setup: run
appium-doctor— fix all warnings
- Launch Appium Inspector and connect to
localhost:4723 - Inspect live elements on a running Android app
- Read
resource-id,content-desc, andclassattributes
- Native apps — platform-specific APK or IPA, fastest performance
- Hybrid apps — native shell wrapping a
WebView - Mobile web apps — browser-based, no install required
- How Appium handles each type differently
- Create and launch Android Virtual Device (AVD emulator)
- Enable USB debugging on a real Android phone
- Confirm the device is visible:
adb devices - Install APK on device:
adb install app.apk - Get
appPackageandappActivitywithadb shell
- Xcode installation and iOS Simulator setup
- Install
appium-xcuitest-driverfor iOS - UDID — unique identifier for real iPhone
bundleId— equivalent of appPackage for iOS apps
By.id()— usingresource-id(most stable)By.xpath()— relative and absolute path expressionsAppiumBy.accessibilityId()— usingcontent-descAppiumBy.androidUIAutomator()withUiSelectortext queriesBy.className()— widget class name fallback- Locator reliability vs performance trade-offs
appPackage— the app's unique ID (e.g.com.android.calculator2)appActivity— the screen Appium launches first- Find both using
adb shell dumpsys window - Verify locators in the Inspector before writing code
DesiredCapabilities— legacy key-value approach (Appium 1.x)UiAutomator2Options— typed, IDE-friendly class (Appium 2.x)- Creating
AndroidDriverusing options + server URL - Appium server URL:
new URL("http://127.0.0.1:4723")
platformName—"Android"or"iOS"deviceName— AVD name or physical device labelautomationName—"UiAutomator2"or"XCUITest"appPackage+appActivityfor installed appsapp— path to APK/IPA for install-on-launchdriver.activateApp()/terminateApp()— switch apps mid-test
element.click()— tap a button or linkelement.sendKeys("text")— type into an input fieldelement.getText()— read the visible textisDisplayed(),isEnabled(),isSelected()element.clear()— empty an input field
driver.findElements()— returns aList<WebElement>- Count items:
list.size() - Access by index:
list.get(n) - Loop through all list items with a
forloop
PointerInput+Sequence— modern swipe and drag- Swipe up/down/left/right using screen coordinates
- Scroll to element with
UiScrollable(Android) - Long press with touch duration
- Pinch and zoom gestures
driver.hideKeyboard()— dismiss soft keyboard
noReset: true— preserve login and data between sessionsfullReset: true— uninstall and reinstall for a clean slate- Default reset — clears app data, keeps app installed
- Choosing the right reset per test scenario
autoGrantPermissions: true— skip all permission pop-upsnewCommandTimeout— prevent session timeout in slow testsunicodeKeyboard/resetKeyboardfor special charactersdriver.getContextHandles()— list available contexts- Switch to WebView:
driver.context("WEBVIEW_*") - Switch back to native:
driver.context("NATIVE_APP")
@BeforeMethod— launchAndroidDriverbefore each test@AfterMethod— quit driver cleanly after each test@BeforeClass/@AfterClass— class-level lifecycle@Test(priority=)— control execution order@Test(groups={"smoke","regression"})— group-based runs
testng.xml— suite file defining which tests runparallel="methods"— run tests simultaneously@DataProvider— feed multiple data sets to one test@Parameters— pass device name from XML configITestListener— hook into pass/fail events
Assert.assertEquals(actual, expected)— text/value matchAssert.assertTrue(condition)/assertFalse()Assert.assertNotNull(object)— element exists- Test stops immediately on assertion failure
SoftAssert sa = new SoftAssert()— one per test methodsa.assertEquals(),sa.assertTrue()— continue on failuresa.assertAll()— report all failures at the end- When to use soft assertions: validating a full screen with multiple fields
- Default HTML report auto-generated in
test-output/ emailable-report.html— shareable summary- Pass/fail/skip breakdown with stack traces
- Add
extentreportsMaven dependency ExtentReports— defines report output pathExtentTest— log steps for each testextentTest.pass()/.fail()/.skip()- Capture screenshot on failure:
TakesScreenshotinterface - Embed screenshot in report:
MediaEntityBuilder - Auto-report via
ITestListener— no boilerplate in each test - Finalise report:
extent.flush()
- Maven project structure:
src/main/java,src/test/java pom.xml— add Appium, TestNG, Extent Reports, Apache POImaven-surefire-plugin— linktestng.xmlfor execution- Run all tests from terminal:
mvn test - Run specific groups:
mvn test -Dgroups=smoke
- Apache POI dependency:
poi-ooxml - Read Excel:
XSSFWorkbook→XSSFSheet→Row→Cell - Build
ExcelUtilshelper class - Feed Excel data into
@DataProviderfor parameterised tests
- One page class per screen — encapsulates locators and actions
- Test classes only call page methods — no locators in tests
- One locator change fixes all tests that use that screen
- Tests read like plain English:
loginPage.enterUsername("admin")
@FindBy(id = "resource-id")field annotation@AndroidFindBy/@iOSXCUITFindByplatform-specific annotationsPageFactory.initElements(driver, this)in page constructor- Lazy loading — elements located only on first interaction
- Project layers:
pages/,tests/,utils/,config/ config.properties— externalise device name, app packageDriverManagerwithThreadLocal<AndroidDriver>for parallel safety
- Install Jenkins:
java -jar jenkins.war - Create Freestyle Job — configure Git SCM + build trigger
- Build step:
mvn test— run suite from Jenkins - Post-build: publish TestNG results and HTML reports
- Parameterised builds — pass
deviceNameas a Jenkins variable - Schedule nightly test runs with cron expression
- Implement
IRetryAnalyzerinterface retry()— returntrueto re-run the failed test- Set max retry count (e.g. 2 retries before final failure)
- Apply globally via
IAnnotationTransformer— no per-test code changes
- Set
platformName: "iOS",automationName: "XCUITest" - Connect real iPhone — trust device, provide UDID
bundleIdcapability for installed iOS app- Run on iOS Simulator using Xcode SimCtl
noReset:true keeps the app state (stays logged in). fullReset:true uninstalls and reinstalls — giving you a completely clean app. Default reset only clears data without uninstalling.UiAutomator2 for Android and XCUITest for iOS. Selenium only works with web browsers. Same API, different target.SoftAssert continues running the test even when a check fails, then reports everything at once via assertAll(). Use it when you want to verify multiple fields on a screen in one test run.appPackage is the app's unique ID (e.g. com.android.calculator2). appActivity is the entry screen Appium launches. Both are required to open an already-installed app without providing the APK.@FindBy and PageFactory. Test classes call page methods instead of using locators directly — making the framework easy to maintain.driver.getContextHandles() to list all contexts, switch to "WEBVIEW_*" to interact with embedded web content, then switch back to "NATIVE_APP" for native elements.