Guides

Appium with Cucumber (Java)

Run a Cucumber feature against an Android build on SpawnDroid, with step definitions, the JUnit Platform suite and the Appium driver lifecycle.

Cucumber is a layer above Appium: the feature file describes the scenario, the step definitions own the driver. This example runs on the JUnit Platform and uses the same UiAutomator2 capabilities as the other Java guides.

Dependencies

Use the current Cucumber, JUnit Platform and Appium Java client releases:

<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-java</artifactId>
  <version>${cucumber.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-junit-platform-engine</artifactId>
  <version>${cucumber.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-suite</artifactId>
  <version>${junit.platform.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.appium</groupId>
  <artifactId>java-client</artifactId>
  <version>${appium.java.client.version}</version>
  <scope>test</scope>
</dependency>

Set the properties to the current releases from Maven Central.

The feature

src/test/resources/features/checkout.feature
Feature: Checkout

  Scenario: Add an item to the cart
    Given the checkout app is open
    When I tap "Add to cart"
    Then the cart total is visible

The steps

src/test/java/steps/CheckoutSteps.java
package steps;

import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.net.URL;
import java.time.Duration;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class CheckoutSteps {
  private AndroidDriver driver;

  @Before
  public void openApp() 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);
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
  }

  @Given("the checkout app is open")
  public void theCheckoutAppIsOpen() {
    assertTrue(driver.currentActivity() != null);
  }

  @When("I tap {string}")
  public void iTap(String label) {
    driver.findElement(AppiumBy.accessibilityId(label)).click();
  }

  @Then("the cart total is visible")
  public void theCartTotalIsVisible() {
    assertTrue(driver
        .findElement(AppiumBy.id("com.acme.checkout:id/total"))
        .isDisplayed());
  }

  @After
  public void closeApp() {
    if (driver != null) driver.quit();
  }
}

The runner

src/test/java/RunCucumberTest.java
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "steps")
public class RunCucumberTest {}

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

Cucumber reports failures per scenario. A failed step still runs the @After hook, so the device is released.

Run it on SpawnDroid

Create a free workspace with 200 device-minutes a month, or read the Java and TestNG guide for the non-BDD version.

Was this page helpful?

On this page