First test in Java
A complete Appium test in Java you can copy, run, and watch on a real phone.
One file. Copy it, put your access key in, run it, and watch it happen on a real device.
What you need
Java 11 or newer, and one dependency:
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>9.3.0</version>
</dependency>Nothing of ours to install. This is the ordinary Appium client.
The whole test
This drives our demo app, so there is nothing to upload — farm://app-sample is already on every device.
import io.appium.java_client.AppiumBy;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.ios.options.XCUITestOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.net.URL;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class FirstMobileTest {
static final String ACCESS_KEY = "xyz_your_access_key_here";
static final String HUB = "https://x:" + ACCESS_KEY + "@hub.testkase.com/wd/hub";
static final String TEST_NAME = "sign in";
public static void main(String[] args) throws Exception {
XCUITestOptions options = new XCUITestOptions();
options.setDeviceName("iPhone 16");
options.setCapability("appium:app", "farm://app-sample");
Map<String, Object> tk = new HashMap<>();
tk.put("name", TEST_NAME);
tk.put("build", "first-test");
tk.put("runId", UUID.randomUUID().toString());
tk.put("recording", true);
options.setCapability("testkase:options", tk);
AppiumDriver driver = new AppiumDriver(new URL(HUB), options);
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
System.out.println("session " + driver.getSessionId());
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(
AppiumBy.accessibilityId("login-email")));
driver.findElement(AppiumBy.accessibilityId("login-email")).sendKeys("test");
driver.findElement(AppiumBy.accessibilityId("login-password")).sendKeys("test");
driver.findElement(AppiumBy.accessibilityId("login-submit")).click();
// The tab bar only appears once sign-in succeeded.
wait.until(ExpectedConditions.visibilityOfElementLocated(
AppiumBy.accessibilityId("tab-counter")));
driver.executeScript("testkase-status=passed");
System.out.println("PASS " + TEST_NAME);
} catch (Throwable t) {
driver.executeScript("testkase-status=failed");
System.out.println("FAIL " + TEST_NAME + " -> " + t.getMessage());
driver.quit();
System.exit(1);
}
driver.quit();
}
}Android instead? Swap XCUITestOptions for UiAutomator2Options, and the accessibility ids stay the same — our demo app uses the same ones on both platforms.
What each part does
Six things carry the whole file. Read down the middle column and you have its shape.
| The part | What it does | |
|---|---|---|
| 1 | https://x:[email protected]/wd/hub | Where your key goes. The same address serves desktop browsers and phones — the capabilities decide which you get. |
| 2 | platformName: "iOS" | Picks the platform. That is all you must send; leave the model and OS version out and you get whichever matching device is free. |
| 3 | appium:app | What to open. farm://app-sample is our demo app — nothing to upload, and it serves the right build for iOS, Android, real or virtual. Swap in your own id once you have uploaded a build. |
| 4 | recording: true | Says what to keep. name is how you will recognise the session in a list; recording is the video, and you get none unless you ask. Every option. |
| 5 | driver.findElement(AppiumBy.accessibilityId(...)) | Ordinary Appium from here on. Every command behaves exactly as it does against a phone on your desk — we only carry it to the device and back. |
| 6 | testkase-status=passed | How we tell a pass from a crash. Without it the session shows no result. The failed one belongs in the catch, because a test that blows up skips every line after the blow-up. |
Run it
mvn -q compile exec:java -Dexec.mainClass=FirstMobileTestThe console prints a session id, then PASS. Open your dashboard while it runs and you can watch the device live; when it ends, the video is on the session.
