A portfolio-style mobile automation framework demonstrating production-grade structure, reporting, and stability patterns using a realistic login flow with multiple outcomes.
Login is intentionally chosen because it is simple in scope but rich in behaviour. This project validates four scenarios:
- Valid credentials → user reaches the secret area and identity is verified.
- Invalid credentials → error/alert is shown.
- Wrong password → error/alert is shown.
- Empty username → error/alert is shown.
The result is a compact suite that still exercises synchronisation, page flows, and robust assertions.
- Page Object Model + flow orchestration for clean separation of concerns, and maintainable test architecture.
- Behavior-Driven Development (BDD) with Cucumber for readable, business-readable scenarios.
- TestNG orchestration with extensible runners.
- CI/CD integration for automated test execution in pipelines for iOS (macOS) and Android (Linux).
- Allure reporting for clear test insights.
- Structured logging for traceability and debugging.
- Failure-proofing techniques to increase test stability and reduce flakiness.
- Defensive UI handling for variable login outcomes (alerts, invalid states).
- Extensible configuration via JSON device profiles.
- Modular design with POM + flows + steps.
- Parallel execution (available on the
developmentbranch).
For users who want to run the project quickly:
# 1. Clone repo
git clone <repo-url>
cd mobile-automation
# 2. Install dependencies
mvn -q -DskipTests install
# 3. Install Appium + driver
npm install -g appium
appium driver install uiautomator2
# 4. Start Appium manually
appium --log-level warnRun tests on iOS:
# 5. Run iOS tests
mvn test -Dplatform=ios
# Optional: generate Allure report
allure serve allure-resultsRun tests on Android:
# 5. Run Android tests
mvn test -Dplatform=android
# Optional: generate Allure report
allure serve allure-resultsThe following step definitions show the full login flow — success and failure paths — using the sealed interface pattern for typed outcomes:
@When("the user logs in with username {string} and password {string}")
public void login(String user, String pw) {
loginResult = loginFlow.login(user, pw);
}
@Then("the secret area should be displayed")
public void secretArea() {
// LoginResult is a sealed interface — assertInstanceOf enforces the expected outcome type
LoginResult.Success success = assertInstanceOf(LoginResult.Success.class, loginResult);
secretPage = success.page();
Assert.assertTrue(secretPage.isVisible());
}
@And("the logged in user should be {string}")
public void verifyUser(String username) {
Assert.assertTrue(
secretPage.loggedInUserText().contains(username),
"Expected username to be displayed"
);
secretPage.logOut();
}
@Then("an invalid login alert should be shown")
public void invalidLogin() {
// Wrong outcome type at runtime = instant, descriptive failure
LoginResult.Invalid invalid = assertInstanceOf(LoginResult.Invalid.class, loginResult);
InvalidLoginDialog dialog = invalid.dialog();
Assert.assertTrue(dialog.isVisible());
dialog.accept();
}LoginResult is a Java 17 sealed interface with two permitted subtypes — Success and Invalid. If the app returns the wrong outcome, assertInstanceOf fails with a clear message naming both types, rather than a null pointer or a silent wrong-state assertion.
mobile-automation/
│
├── .github/workflows/ # CI pipelines
├── apps/ # Demo apps (iOS/Android)
├── allure-results/ # Allure result files
├── logs/ # Local logs (if enabled)
├── src/test/java/com/mobileAutomation/
│ ├── assertions/ # Custom assertions
│ ├── config/ # Config loaders
│ ├── driver/ # Driver factory and manager
│ ├── flows/ # Flow orchestration
│ ├── hooks/ # Cucumber hooks
│ ├── pages/ # Page Object Model
│ ├── runners/ # TestNG runners
│ └── steps/ # Cucumber step definitions
├── src/test/resources/
│ ├── config/ # Device configs (android.json, ios.json)
│ └── features/ # BDD .feature files
│
├── pom.xml
└── README.md
This section documents how to set up your machine for Appium-based mobile test automation development.
Read more..
This project requires Java 17 and Maven.
Verify versions:
java -version
mvn -versionAppium is installed via npm:
node -v
npm -v
npm install -g appiumInstall the Android driver:
appium driver install uiautomator2macOS is required for iOS automation. You must have:
- Xcode installed
- Command Line Tools installed
- iOS Simulator available
Verify Xcode:
xcodebuild -version
xcrun simctl list devicesAndroid automation requires the Android SDK and an emulator or device. Verify SDK tools:
adb version
emulator -versionAllure Reporting provides rich, visual test reports generated from your framework.
Read more..
macOS (Homebrew):
brew install allureWindows: Download the Allure ZIP from the official distribution page, extract it, and add the bin folder to your system path.
Linux:
sudo apt-add-repository ppa:qameta/allure
sudo apt-get update
sudo apt-get install allureVerify installation:
allure --versionAfter running your tests, an Allure results folder will be created. To generate and view the report:
allure serve allure-resultsThis command builds the report and opens it in your browser.
This project uses Maven, TestNG, and Cucumber to run the automation suite.
Parallel test execution is implemented on the development branch. If you want parallel runs, switch to that branch and follow the branch-specific README instructions.
Update iOS device config:
cat src/test/resources/config/ios.jsonRun:
mvn test -Dplatform=iosUpdate Android device config:
cat src/test/resources/config/android.jsonRun:
mvn test -Dplatform=androidGitHub Actions workflows live under:
.github/workflows/They run iOS on macOS runners and Android on Ubuntu runners.
A collection of common issues and quick fixes for running the mobile automation project.
Symptom: SessionNotCreatedException or ECONNREFUSED to Appium server.
Fix:
appium --log-level warn --port 4723Symptom: adb: device offline or boot never completes.
Fix:
adb kill-server
adb start-server
adb devicesSymptom: WDA session takes several minutes.
Fix:
- Ensure Xcode is installed and set as active
- Pre-boot the simulator before running tests
xcrun simctl boot "<device-name>" || true
xcrun simctl bootstatus "<device-name>" -bSymptom: Allure opens a report with 0 tests.
Fix:
- Ensure tests ran before generating the report
- Verify
allure-resultsexists
ls -la allure-results