Setup for Appium Testing or UIAutomator
Before you run your tests with Appium or UIAutomator, equip your application with the floating action button of axe DevTools for Android.
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:
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
.
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);
}
}