🧪 Real Scenario — Product Search & Add to Cart

Real Scenario — Product Search & Add to: Writing an E2E mobile flow is like giving directions to a courier: say "turn right at the bakery" and they will find it, but say "turn ri

Writing an E2E mobile flow is like giving directions to a courier: say "turn right at the bakery" and they will find it, but say "turn right after 45 metres" and they get lost the day the pavement changes. Across Launch app → Search product → View detail → Add to cart → Verify cart you make exactly that call at every step: a meaningful landmark (accessibility id) or a brittle coordinate (XPath index)? So if the test goes green either way, why does the choice of locator matter so much? On the Java (JUnit 5 + Appium) side a `WebElement` feels just like Selenium — but unlike Selenium the screen can ROTATE, the keyboard can COVER the element, and the same screen lays out differently on another device; the same holds on the TypeScript (WebdriverIO) side. In QA terms the cost is concrete: a cart test built on index-based locators breaks in the nightly build the moment one banner is added to the app, and next morning the team debates test maintenance instead of a real bug.

Test Scenario & Project Structure

Project Folder Structure

BasePage contains common wait, scroll, screenshot methods. Test classes focus only on business logic.

Java — BaseTest (Driver Setup)

BaseTest.java — Appium Driver Management with JUnit 5

Micro Lab: Code practice

Replace the TODO line with the critical line from the expected solution. This is not a real runtime; the goal is to reinforce writing the correct structure in a controlled way.

Why Do @BeforeAll/@AfterAll Run Only Once Per Test Class?

protected static AndroidDriver driver…

`protected static AndroidDriver driver` — the `static` field, just like REST Assured's `spec`, makes the driver SHARED across ALL test methods; no test OPENS a new driver.

@BeforeAll static void setUp() sets up…

`@BeforeAll static void setUp()` sets up the APP and emulator connection ONLY ONCE, BEFORE the FIRST test in the class runs — repeating this in every `@Test` would make EVERY test much SLOWER.

`driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10))` sets a DEFAULT wait for ALL `findElement` calls — WITHOUT this, EVERY call searching for a not-yet-loaded element would FAIL instantly.