Setup for Appium Testing or UIAutomator

Link to Setup for Appium Testing or UIAutomator copied to clipboard

Before you run your tests with Appium or UIAutomator, equip your application with the floating action button of axe DevTools for Android.

tip

Appium or UIAutomator testing is only support with XML views today. Support for more views and codeless testing is coming later this year.

Setup

In order to use the DashboardService API with your Appium project, make sure mavenCentral() repository and com.deque.android:axe-devtools-android-core:3.2.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:3.2.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.

DashboardService.connect(“apiKey”, ConnectionConfig)

Connect with username and password:

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

Disconnect

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

DashboardService.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();

DashboardService 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();
        DashboardService.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 DashboardService.getResultSync(AxeDevToolsResultKey.fromPath(resultKey));
    }

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

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

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