Setup for Appium

Link to Setup for Appium copied to clipboard
tip

We're developing an Appium Plugin that's set to launch later this year. This plugin will enable you to better integrate accessibility testing throughout your Appium tests, no matter the language they are written in!

Using Appium with axe DevTools Today?

Before running the Appium test, ensure the apk being passed into Appium runs axe DevTools on the screens you want to test with axe.showA11yFab(activity) and is connected to the dashboard with axe.connect(...). Check out our guide to setting up your app for Appium testing.

Setup

In order to use the ResultsDashboard API with your Appium project, make sure mavenCentral() repository and com.deque.android:axe-devtools-android-core:4.1.0 dependency are added to the project's build.gradle.

Example

plugins {
    id 'java'
    id 'org.jetbrains.kotlin.jvm' version '1.5.0'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.google.com" }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib"
    implementation "junit:junit:4.13.2"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2"
    testImplementation "junit:junit:4.13.1"

    implementation "com.deque.android:axe-devtools-android-core:4.1.0"

    implementation "com.github.appium:java-client:8.1.1"
    implementation "org.seleniumhq.selenium:selenium-java:4.2.1"
}

Initialize the Connection

Initialize a connection to the server with one of the following:

note

ConnectionConfig is an optional parameter for connection to a private cloud instance of axe DevTools Mobile.

Connect with an API key:

Generate an API key at axe.deque.com.

ResultsDashboard().connect(“apiKey”, ConnectionConfig)

Connect with username and password:

ResultsDashboard().connect(“username”, “password”, ConnectionConfig)

Disconnect

If you need to disconnect at any point, please use the following API:

ResultsDashboard().disconnect()

Run a Scan

Once you've established a connection, initiate a scan by clicking the floating action button through the Appium framework.

driver.findElement(
    new AppiumBy.ByAndroidUIAutomator("description(\"Axe\")")
).click();

ResultsDashboard API

Once you've sent a scan to the dashboard by tapping the floating action button, you can utilize the following APIs to interact with the result.

APIs that require param:

Type Description
AxeDevToolsResultKey Unique identifier of a scan on the server. Populated after a successful run in the content description of the floating action button.

getResult(param)

Fetches a scan result from the dashboard. Synchronous alternative: getResultSync(param)

deleteResult(param)

Deletes a scan result from the dashboard. Synchronous alternative: deleteResultSync(param)

tag(param)

Updates your scan to include the provided tags. Synchronous alternative: tagSync(param)

Required param in addition to AxeDevToolsResultKey highlighted above:

Type Description
List<String> List of Strings that represent the tags you'd like to add to the specific scan result.

setScanName(param)

Updates the displayed scan name in the dashboard. Synchronous alternative: setScanName(param)

Required param in addition to AxeDevToolsResultKey highlighted above:

Type Description
String Defines the name of the scan.

getUserInfo()

Helpful for debugging authentication - an authenticated session will return a JSON object containing user information such as email.

getHealthCheck()

Helpful for debugging connection - a successful connection will return a JSON object indicating the server status is UP.

tip

Synchronous alternatives can be used and do not need to be called from a coroutine context.

Example Appium Test in Java

public class AppiumTest {
    AndroidDriver driver;

    AndroidDriver makeDriver() throws MalformedURLException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
        capabilities.setCapability(MobileCapabilityType.APP, new File( "/path/to/app.apk").getAbsolutePath());
        capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
        capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);

        String DEFAULT_APPIUM_ADDRESS = "http://0.0.0.0:4723/wd/hub";
        return new AndroidDriver(new URL(DEFAULT_APPIUM_ADDRESS), capabilities);
    }

    @Before
    public void setup() throws MalformedURLException {
        driver = makeDriver();
        ResultsDashboard().connect(
                "your-api-key-here",
                new ConnectionConfig(
                        AxeDevToolsClient.DEFAULT_REALM,
                        AccessToken.DEFAULT_URL,
                        AxeDevToolsClient.DB_DEFAULT_URL
                )
        );
    }

    @Test
    public void test() {
        AxeDevToolsResult result = a11yResult();

        setScanName(result.getAxeDevToolsResultKey(), "Appium Test");
        tagResult(result.getAxeDevToolsResultKey(), "Appium");

        result.getAxeResult().axeRuleResults.forEach((axeResult) -> {
            if (axeResult.status.equals(AxeStatus.FAIL)) {
                System.out.println(axeResult.toString());
            }
        });

        // optionally delete a result
        // deleteResult(result.getAxeDevToolsResultKey());
    }

    private AxeDevToolsResult a11yResult() {
        driver.findElement(
                new AppiumBy.ByAndroidUIAutomator("description(\"Axe\")")
        ).click();

        WebDriverWait webDriverWait = new WebDriverWait(driver, Duration.ofSeconds(10));
        webDriverWait.until((ExpectedCondition<Boolean>) input -> {
            if (input != null) {
                input.findElement(AppiumBy.id("result_key_container"));
            }
            return true;
        });

        String resultKey = driver.findElement(
                AppiumBy.id("result_key_container")
        ).getAttribute("content-desc");

        return ResultsDashboard().getResultSync(AxeDevToolsResultKey.fromPath(resultKey));
    }

    private void setScanName(AxeDevToolsResultKey resultKey, String scanName) {
        ResultsDashboard().setScanNameSync(resultKey, scanName);
    }

    private void tagResult(AxeDevToolsResultKey resultKey, String tag) {
        List<String> tagList = new ArrayList<>();
        list.add(tag);
        ResultsDashboard().tagSync(resultKey, tagList));
    }

    private void deleteResult(AxeDevToolsResultKey resultKey) {
        ResultsDashboard().deleteResultSync(resultKey);
    }
}