The capstone is complete when the full test suite runs reliably on both platforms, with screenshots on failure, Allure reporting, and CI integration. This lesson covers the self-review checklist, common final mistakes, and where to take your skills next.
Self-review checklist
Work through each item before considering the capstone done:
Project structure
-
DriverManagerusesThreadLocal<AppiumDriver>— no shared static fields -
BaseTeststarts/stops the Appium server in@BeforeSuite/@AfterSuite - Driver is created in
@BeforeTest, destroyed in@AfterTest - Page objects extend
BasePageand have no assertions - Tests extend
BaseTestand have no locators
Locators
- All locators use
accessibilityId, UIAutomator, or predicate strings - No XPath used (if any XPath exists, document why)
- Locator constants are
private static final By - No hardcoded coordinates (except in
GestureUtils)
Waits
- No
Thread.sleep()anywhere in the codebase -
waitForVisibleandwaitForClickableused in page objects - Loading spinners are waited on before asserting on results
Parallelism
-
testng-smoke.xmlruns Android and iOS simultaneously - Each
@BeforeTestreceivesplatformparameter from XML - Test output shows two concurrent sessions in the Appium log
Reporting
-
ScreenshotListenersaves PNG totarget/screenshots/on failure -
RetryTransformeris listed intestng.xmllisteners -
@Epic,@Feature,@Storyvisible in Allure report -
@NoRetryapplied to the checkout test (or wherever retry would cause duplicate orders)
CI
-
testng-smoke.xmlcompletes in under 3 minutes on GitHub Actions - Allure results are uploaded as a workflow artifact
- No credentials in committed code (environment variables only)
Common final mistakes
Driver leak on test failure: If a test fails mid-setup (before the driver is fully ready), @AfterTest may try to quit a null driver. Guard against it:
@AfterTest
public void tearDown() {
AppiumDriver driver = DriverManager.getDriver();
if (driver != null) {
driver.quit();
DriverManager.removeDriver();
}
}Shared page object state: Creating a page object in @BeforeClass and reusing it across test methods means method B inherits any state mutation from method A. Always construct fresh page objects in @BeforeMethod or at the start of each test.
Appium server still running after suite: If AppiumServiceBuilder throws during startup and the server partially started, @AfterSuite may not clean it up. Add a JVM shutdown hook as a safety net:
@BeforeSuite
public void startServer() {
AppiumServer.start();
Runtime.getRuntime().addShutdownHook(new Thread(AppiumServer::stop));
}Flaky scroll tests on CI: Emulators in CI have lower frame rates than local machines. Scroll gestures that work locally may overshoot or undershoot. Increase the gesture duration and reduce scroll distance on CI:
boolean isCI = Boolean.parseBoolean(System.getenv("CI"));
Duration scrollDuration = isCI ? Duration.ofMillis(1000) : Duration.ofMillis(500);What comes next
XCUITest for iOS-native deep dives
Appium's iOS support is excellent, but XCUITest gives you access to performance metrics, accessibility audits, and Xcode's recording tools that Appium can't reach. If your app is iOS-first, add an XCUITest target for the scenarios that need native precision.
Espresso for Android in-process testing
Espresso tests run in the same process as the app, which means they see private state, synchronise automatically with the main thread, and run 5–10× faster than Appium. Use Espresso for unit-level UI tests that don't need cross-platform parity.
Device farms at scale
The BrowserStack setup from Chapter 6 handles 4 devices. For 40 devices, you need a real parallelism strategy: shard the test suite by feature area, run each shard on a dedicated device, and aggregate Allure results after all shards complete.
Performance baselines
The next quality problem after functional coverage is performance regression. Measure cold start time, frame drops during scroll, and memory usage under load. Add assertions: if cold start exceeds 3 seconds, the test fails.
Accessibility scanning
Appium's mobile: accessibilityAudit command (iOS) and the Accessibility Test Framework for Android can scan the current screen for WCAG violations. Add a scan to each page object's constructor and log violations to the Allure report.
These specialisations are covered in the Mobile Testing roadmap path — the Appium foundation you've built here is the prerequisite for all of them.