Reference for XML Layout Testing
Utilizing the XML APIs today?
To streamline the implementation of axe DevTools Mobile for Android we have deprecated the XML and Compose APIs. We encourage you to switch to the layout agnostic APIs for continued support and access to the latest updates. With the layout agnostic APIs you can scan screens with XML layouts, Compose layouts, or both, all with one API call.
This page highlights the steps for setting up the library to scan android applications with XML layouts for accessibility issues. For steps to pull in the library, please see Getting Started with the Android SDK.
Automated Testing
Before running Espresso tests, initialize the main entry for the AxeDevTools
library.
Initialize the Library
In the test class init, connect to the library with one of the following:
Connect with API key:
Generate an API key at axe.deque.com.
private val axe = AxeDevTools()
init {
axe.loginWithApiKey(
"DEQUE_API_KEY"
)
}
Connect with username and password:
private val axe = AxeDevTools()
init {
axe.loginWithUsername(
"DEQUE_USERNAME",
"DEQUE_PASSWORD"
)
}
Run a Scan
When you're ready to run a scan from your tests, you'll want to run axe.scan(...)
. We've included a function below that highlights some additional functionality you may find helpful.
Read about these features and more on the Android Features page. This function is broken down below the snippet.
private fun a11yScan() {
rule.scenario.onActivity { activity ->
//1. Scan and receive the ScanResultHandler locally
val scanResultHandler = axe.scan(activity)
//2. Upload it to the dashboard
scanResultHandler?.uploadToDashboard()
//3. Using the results in your test suite
val result: AxeResult? = scanResultHandler?.getSerializedResult()
result?.axeRuleResults?.forEach { result ->
if(result.status == AxeStatus.PASS) {
}
else if(result.status == AxeStatus.FAIL) {
}
else if(result.status == AxeStatus.INCOMPLETE) {
}
}
//4. Save the result JSON to a local file for later use
scanResultHandler?.saveResultToLocalStorage("your_file_prefix")
}
}
Code snippet breakdown:
- Call
axe.scan(activity)
anytime the UI should be scanned. The scan function can be called multiple times within the same test run. The current activity will be scanned for accessibility issues, and a scan result handler will be returned. - From the result handler, call
uploadToDashboard()
to send the most recent scan to the dashboard. The scan will be published from the authenticated account used in the init function. - From the result handler, call
getSerializedResult()
to use results from the library locally. For example, you may choose to fail the test when failures are found in the accessibility scan results. This will not upload your results to the server. Uploading your results is not required to get the results locally. - From the result handler, call
saveResultToLocalStorage()
to save the results as JSON in a local file within your test device. To access the saved file, refer to the feature documentation for Saving Results Locally.
Scan a Dialog
Released with version 3.1.0, axe DevTools for Android now supports scanning dialogs. From your dialogs Dialog.show()
method, pass the returned dialog as a parameter to the scan
method as well as a callback to handle the scan's result. The callback returns a ScanResultHandler
by default so that you may handle the result as you see fit. See the following example:
Kotlin Example:
val dialog = AlertDialog.Builder(requireContext())
.setTitle("Title")
.setMessage("Message")
.show()
MainScope().launch {
delay(5000)
axe.scan(dialog) { handler ->
handler?.uploadToDashboard()
}
}
When scanning a dialog the scan itself will take place immediately after the dialog has been inflated in automated testing. Note that a scan will only take place if the following are true:
- The user is authenticated
- Espresso tests are running
- The dialog is inflated before the timeout expires
Deinitialize
Once the test has been completed, call tearDown()
on the AxeDevTools object you have created to clear the state of previous tests. We recommend putting this in your testing file's tearDown
function, but it can also be called within a test if needed.
@After
fun tearDown() {
axe.tearDown()
}
Example Espresso Test Class for XML
class ExampleInstrumentedTestWithAccessibility : Utils {
@Rule
@JvmField
var rule: ActivityScenarioRule<MainActivity> = ActivityScenarioRule(MainActivity::class.java)
private val axe = AxeDevTools()
init {
//Connect using an API Key
axe.loginWithApiKey(
"DEQUE_API_KEY"
)
}
@Before
fun setup() {
axe.tagScanAs(setOf("ScanningApp"))
axe.setTestingConfig(AxeDevToolsEspressoConfig(IdlingRegistry.getInstance()))
}
@Test
fun exampleTest() {
onView(withText("Active View Name")).perform(click())
onView(withText("Actionable Button")).perform(click())
onView(withContentDescription("Share Data")).perform(click())
}
@After
fun runAccessibilityScan() {
rule.scenario.onActivity {
val scan = axe.scan(it)
scan?.uploadToDashboard()
axe.tearDown()
}
}
}
Scan Dialog Espresso Example
class ExampleInstrumentedTestWithAccessibility : Utils {
private lateinit var countingResource: CountingIdlingResource
@Before
fun setTestingConfig() {
countingResource = CountingIdlingResource("DialogScan")
IdlingRegistry.getInstance().register(countingResource)
axe.setTestingConfig(AxeDevToolsEspressoConfig(IdlingRegistry.getInstance()))
}
@Test
fun dialogScan() {
countingResource.increment()
rule.scenario.onActivity { activity ->
val dialog = AlertDialog.Builder(activity)
.setTitle("Title")
.setMessage("Message")
.show()
axe.scan(dialog) { handler ->
val result = handler?.uploadToDashboard()
countingResource.decrement()
}
}
while(!countingResource.isIdleNow) { Thread.sleep(100) }
}
@After
fun tearDown() {
IdlingRegistry.getInstance().unregister(countingResource)
axe.tearDown()
}
}
API Reference
loginWithUsername(params)
Generates an auth token to connect to the dashboard.
Required params
:
Name | Type | Description |
---|---|---|
username | String |
Deque username |
password | String |
Deque password |
Optional param
:
Name | Type | Description |
---|---|---|
serverConfig | String |
Defines the server URL to connect to. |
loginWithApiKey(param)
Generates an auth token to connect to the dashboard.
Required param
:
Name | Type | Description |
---|---|---|
apiKey | String |
Deque API key |
Optional param
:
Name | Type | Description |
---|---|---|
serverUrl | String |
Defines the server URL to connect to. |
disconnect()
Clears the current axe DevTools network session to allow a new connection to be made.
isUserAuthenticated()
Returns a boolean to indicate whether the user is authenticated and ready to send scans.
Returns:
Type | Description |
---|---|
Boolean | Indicates whether a user is authenticated for axe DevTools Mobile. |
setScanName(param)
Set a name to the scan before uploading it to the dashboard.
Required param
:
Name | Type | Description |
---|---|---|
name | String |
Name for the scan. |
tagScanAs(param)
Tags a scan before uploading it to the dashboard.
Required param
:
Name | Type | Description |
---|---|---|
tags | Set<String> |
List of tags to add to the scan. |
addCustomRule(param)
Add a rule to run against your application during scans.
Required param
:
Name | Type | Description |
---|---|---|
customRule | Class<AxeDevToolsRule> |
Rule to add |
resetIgnoredRules()
Clear the ignored Rules list set by the ignored rules APIs. Helpful for changing rule configuration between automated tests.
ignoreRules(param)
Ignores rules completely from being run against any view.
Required param
:
Name | Type | Description |
---|---|---|
rulesToIgnore | List<String> |
List of rules to ignore. |
ignoreByViewId(param)
Ignores all rules provided for a given viewId.
Required param
:
Name | Type | Description |
---|---|---|
viewId | Int |
ViewId to ignore. |
ruleList | List<Class<out AxeRule>> |
List of rules to ignore. |
ignoreAllByViewId(param)
Ignores all rules for the provided viewIds.
Required param
:
Name | Type | Description |
---|---|---|
viewIds | List<Int> |
List of viewIds to ignore all rules on. |
ignoreByView(param)
Ignores all rules provided for a given View
.
Required param
:
Name | Type | Description |
---|---|---|
view | View |
An instance of a view to ignore. |
ruleList | List<Class<out AxeRule>> |
List of rules to ignore. |
ignoreAllByView(param)
Ignores all rules for the provided View
's.
Required param
:
Name | Type | Description |
---|---|---|
viewIds | List<View> |
List of View to ignore all rules for. |
ignoreByClassName(param)
Ignores all rules for a given type that extends View.
Required param
:
Name | Type | Description |
---|---|---|
view | Class<out View> |
Class to ignore. |
ruleList | List<Class<out AxeRule>> |
List of rules to ignore. |
ignoreAllByClassName(param)
Ignores all rules for the provided types, which extend View.
Required param
:
Name | Type | Description |
---|---|---|
classNames | List<Class<out View>> |
List of Class es to ignore all rules on. |
tearDown()
Resets tags and clears test state from prior testing.
getResult(param)
Requests a scan's result from the dashboard matching the provided result key.
Required param
:
Name | Type | Description |
---|---|---|
axeDevToolsResultKey | AxeDevToolsResultKey |
The identifier of the result you'd like to grab. |
Returns:
Type | Description |
---|---|
AxeDevToolsResult | Nullable AxeDevToolsResult provides access to details of the result. |
deleteResult(param)
Delete a scan's result from the dashboard matching the provided result key.
Required param
:
Name | Type | Description |
---|---|---|
axeDevToolsResultKey | AxeDevToolsResultKey |
The identifier of the result you'd like to grab. |
ScanResultHandler
uploadToDashboard(param)
Upload the accessibility scan's result to the dashboard. By default, the full result object is returned.
Optional param
:
Name | Type | Description |
---|---|---|
uploadOnly | Boolean |
Optional, default is false. When set to true, the result is uploaded to the dashboard and the result key is only available within the AxeDevToolsResult object. |
Returns:
Type | Description |
---|---|
AxeDevToolsResult | Nullable AxeDevToolsResult provides access to details of the result. |
saveResultToLocalStorage(param)
Save the accessibility scan result to a local file on your test device.
Required param
:
Name | Type | Description |
---|---|---|
prefixFilename | String |
Beginning of the filename to save the result as. |
getSerializedResult()
Grabs the result of your scan to use within the test.
Deprecated
connect(params)
Generates an auth token to connect to the dashboard.
Required params
:
Name | Type | Description |
---|---|---|
username | String |
Deque username |
password | String |
Deque password |
Optional param
:
Name | Type | Description |
---|---|---|
serverUrl | ConnectionConfig |
Defines the server to connect to. ConnectionConfig.DEFAULT_CONNECTION_CONFIG will connect you to axe-mobile.deque.com . |
connect(param)
Generates an auth token to connect to the dashboard.
Required param
:
Name | Type | Description |
---|---|---|
apiKey | String |
Deque API key |
Optional param
:
Name | Type | Description |
---|---|---|
serverConfig | ConnectionConfig |
Defines the server to connect to. ConnectionConfig.DEFAULT_CONNECTION_CONFIG will connect you to axe-mobile.deque.com . |
setTestingConfig(param)
Registers an idling resource for the library.
Required param
:
Name | Type | Description |
---|---|---|
config | AxeDevToolsEspressoConfig |
Testing configuration to load. |
scan(param)
Scans an activity's view for accessibility issues.
Required param
:
Name | Type | Description |
---|---|---|
activity | Activity |
Instance of the Activity to scan. |
Returns:
Type | Description |
---|---|
ScanResultHandler | Nullable ScanResultHandler provides a way to get more detailed information on the result or further update the scan by providing a name or tags. |
scan(param)
Scans the provided dialog for accessibility issues and returns a callback.
Required param
:
Name | Type | Description |
---|---|---|
dialog | Dialog |
Instance of the Dialog to scan. |
scanCallback | DialogScanCallback |
Provides aScanResultHandler after the dialog has inflated and the scan has completed. |
Returns:
Type | Description |
---|---|
ScanResultHandler | Nullable ScanResultHandler provides a way to get more detailed information on the result or further update the scan by providing a name or tags. |