Guides

Appium with Java and TestNG

A working TestNG class for an Android build on SpawnDroid, including the Appium Java client setup, capabilities and teardown.

A TestNG suite is a thin wrapper around the Appium Java client. SpawnDroid supplies the endpoint and the installed build; the test supplies the capabilities and assertions.

Dependencies

Add the current Appium Java client and TestNG to pom.xml. Set the two properties to the releases shown on Maven Central; the test code is version-independent.

<properties>
  <appium.java.client.version>REPLACE_ME</appium.java.client.version>
  <testng.version>REPLACE_ME</testng.version>
</properties>

<dependency>
  <groupId>io.appium</groupId>
  <artifactId>java-client</artifactId>
  <version>${appium.java.client.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.testng</groupId>
  <artifactId>testng</artifactId>
  <version>${testng.version}</version>
  <scope>test</scope>
</dependency>

The test

src/test/java/CheckoutTest.java
import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.Assert;
import org.testng.annotations.*;
import java.net.URL;

public class CheckoutTest {
  private AndroidDriver driver;

  @BeforeClass
  public void setUp() throws Exception {
    DesiredCapabilities caps = new DesiredCapabilities();
    caps.setCapability("platformName", "Android");
    caps.setCapability("appium:automationName", "UiAutomator2");
    caps.setCapability("appium:udid", System.getenv("SPAWNDROID_UDID"));
    caps.setCapability("appium:appPackage",
        System.getenv("SPAWNDROID_APP_PACKAGE"));
    caps.setCapability("appium:autoGrantPermissions", true);

    driver = new AndroidDriver(
        new URL(System.getenv("SPAWNDROID_WD_URL")), caps);
  }

  @Test
  public void addsItemToCart() {
    driver.findElement(AppiumBy.accessibilityId("Add to cart")).click();
    boolean visible = driver
        .findElement(AppiumBy.id("com.acme.checkout:id/total"))
        .isDisplayed();
    Assert.assertTrue(visible, "Cart total should be visible");
  }

  @AfterClass(alwaysRun = true)
  public void tearDown() {
    if (driver != null) driver.quit();
  }
}

@AfterClass(alwaysRun = true) matters: a failed assertion must still close the session, or the device stays reserved until the idle reaper stops it.

Run it

export SPAWNDROID_WD_URL='https://stream.spawndroid.io/ci/sess_…/token/wd/hub'
export SPAWNDROID_UDID='emulator-5554'
export SPAWNDROID_APP_PACKAGE='com.acme.checkout'
mvn test -Dsurefire.suiteXmlFiles=testng.xml

Surefire writes JUnit XML under target/surefire-reports. Pass that directory or file to report-path in CI so the run page shows the failing test names.

Android driver imports

With Appium 3 and the Java client, use io.appium.java_client.android.AndroidDriver and AppiumBy. The older MobileBy is deprecated. AppiumBy.accessibilityId maps to the app's content description; AppiumBy.id takes the full package:id/name resource id.

In CI

- uses: kl3jvi/spawndroid/actions/android-test@v1
  with:
    api-key: ${{ secrets.SPAWNDROID_API_KEY }}
    app-path: app/build/outputs/apk/debug/app-debug.apk
    command: mvn test
    report-path: target/surefire-reports/TEST-CheckoutTest.xml

Run it on SpawnDroid

Create a free workspace with one runner and 200 device-minutes, or read the capabilities guide first.

Was this page helpful?

On this page