Reference for Compose Layout Testing

Link to Reference for Compose Layout Testing copied to clipboard
Not for use with personal data
note

Utilizing the Compose 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 Compose layouts for accessibility issues. For steps to pull in the library, please see Getting Started with the Android SDK.

Automated Testing

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 = AxeDevToolsCompose()

init {
     axe.loginWithApiKey(
        "DEQUE_API_KEY"
    )
}

Connect with username and password:

private val axe = AxeDevToolsCompose()

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 helper 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() {
    /*
    Note: This test relies on the compose test rule from `setup` method. Please see the full example at the bottom of this guide.
    */

    val scanResultHandler = axe.scan()

    //1. Upload it to the dashboard
    scanResultHandler?.uploadToDashboard()

    //2. 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) {

        }
    }

    //3. Save the result JSON to a local file for later use
    scanResultHandler?.saveResultToLocalStorage("your_file_prefix")
}

Code snippet breakdown:

  1. 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.
  2. 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.
  3. 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.

Deinitialize

Once the test has been completed, call tearDown() on the AxeDevToolsCompose 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 Compose


@ExperimentalComposeUiApi
class ExampleComposeTest {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<TestComposeActivity>()

    private val axe = AxeDevToolsCompose()

    init {
        // Connect using an API key 
        axe.loginWithApiKey(
            "DEQUE_API_KEY"
        )
    }

    @Before
    fun setup() {
        composeTestRule.setContent { YourComposableFunction() }
        composeTestRule.mainClock.autoAdvance = false
        composeTestRule.waitForIdle()

        axe.tagScanAs(setOf("ScanningAnApp"))
    }

    @Test
    fun foobar() {
        // Must be set in the tests itself
        axe.setComposeTestRule(composeTestRule)
        val scan = axe.scan()
        scan?.uploadToDashboard()
        axe.tearDown()
    }
}

API Reference

All of the public classes and functions below are now deprecated.

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.

connect(params)

Generates an auth token to connect to the dashboard.

Required params:

Name Type Description
username String Deque username
password String Deque password
serverConfig ConnectionConfig Defines the server to connect to. ConnectionConfig.DEFAULT_CONNECTION_CONFIG will connect you to axe-mobile.deque.com.

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.

connect(param)

Generates an auth token to connect to the dashboard.

Required param:

Name Type Description
apiKey String Deque API key
serverConfig ConnectionConfig Defines the server to connect to. ConnectionConfig.DEFAULT_CONNECTION_CONFIG will connect you to axe-mobile.deque.com.

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.

setComposeTestRule(param)

Provides test data to the library.

Required param:

Name Type
composeTestRule ComposeContentTestRule

setEmptyComposeTestRule(params)

This API helps when your test set up is using Compose Empty Test Rule with an Activity to run UI tests in Compose. The activity will be passed in to provide more information to the library such as: title of the screen, package name, etc. View a full example using this API.

Required param:

Name Type
composeEmptyTestRule ComposeTestRule
activity Activity

ComposeTestRule is apart of androidx.compose.ui.test.junit4. Read more on ComposeTestRule.

setTestTag(param)

This API allows you to target a specific composable for testing by providing its test tag.

Required param:

Name Type
tag String

Test Tags are provided by Jetpack Compose to attach a unique identifier to the composables. Read more on TestTag. View a complete example of how to use this API. The setTestTag API can also be used when the No View initialized, did you call AxeDevToolsCompose.setComposeTestRule()? error is encountered while scanning.

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 prior to 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<AxeDevToolsComposeRule> 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.

tearDown()

Resets tags and clears test state from prior testing.

scan()

Scans the view for accessibility issues.

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.

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.