Writing Accessibility Tests with Espresso
Tags: android, mobile, a11y, testing
Published: 2023-04-10 14:51:10

Espresso is Android's UI testing library that allows for simple and concise test creation. Even better, it comes with its own accessibility testing library that lets developers add in checks for accessibility issues in the content they create.

So if it includes something so simple to add to check for accessibility, why is it not used more often? And if it is such a simple library to write UI tests, why haven't more developers made more accessibility regression tests? 

Let's fix that problem and dive into how to take advantage of the accessibility library and how to build regression tests for accessibility!


## Using Accessibility Checks

Included with Espresso is the `AccessibilityChecks` class. This class uses the [Accessibility Test Framework](https://github.com/google/Accessibility-Test-Framework-for-Android) that is used throughout all of Androids products. Using it is extremely simple. 

### Setup and Use

First you need to import the library into your project: 

``` kotlin

import androidx.test.espresso.accessibility.AccessibilityChecks

```
Next, in your setup function, you will need to enable the `AccessibilityChecks` class.

``` kotlin

@Before
fun setup() {  
   AccessibilityChecks.enable()
}

```

Guess what? That is it! You simply have to add this in your setup functions and the library does the rest. 

So how does it work? Well its actually pretty unique compared to other testing libraries. Instead of scanning an entire view, it will run a check when any action defined in `ViewActions` is called. 

For example if we had a test where we entered login information into edit text fields, the `ViewAction` of `typeText` would validate on that action. 

``` kotlin

    @Test
    fun loginInfoEntered() {
        onView(withId(R.id.username)).perform(typeText("Steady"), closeSoftKeyboard())
        onView(withId(R.id.username)).check(matches(withText("Steady")))
        onView(withId(R.id.password)).perform(typeText("A11yIsAwesome"), closeSoftKeyboard())
    }

```

Subsequently, you can enable the check to scan the entire view  and not just the item that had the action as well by adding `.setRunChecksFromRootView(true)`.

### The Good, The Bad

Let's start with the good: 

* Easy and simple setup to add into your project. 
* Checks for 14 different issues. 
     * Credit [Quintin Balsdon article](https://qbalsdon.github.io/accessibility,/testing,/unit/tests/2023/01/04/accessibility-testing.html)
* Can ensure simple regression is done on new content
* Ensures developers learn as they code! 

Now for the bad: 

* Can suppress any and all rules
* Runs on `ViewAction`, not very flexible for test creation
* Gives false sense that this is all the automation needed

Using this library has more positives than negatives, as at least there is accessibility testing being done in your Espresso tests. However, this is only generic testing of your UI content. How do we build upon what the accessibility testing library gives us? Building our own regression tests!

## Accessibility Regression Tests

Usually automated libraries catch around the lower 1/3 of the  issues. We can go beyond just checking generically and write specific regression tests that ensure the accessible functionality of the component or page we created. 

When we say accessible functionality, we are not talking replacing screen reader testing or a manual audit. It is quite the opposite actually. We are talking about building specific tests that check the functionality of the content we created to ensure it is behaving properly from an accessibility perspective. 

An example of this would be checking that focus properly opens into a navigation drawer or tray. Whenever it opens, we would want focus to go into the component itself. Here as a very simplistic example: 

``` kotlin

@Test
fun a11yFocusIntoTray() {
   onView(withId(R.id.moreOptions)).perform(click())
        
   onView(withId(R.id.more_options_tray))
       .check(matches(isDisplayed()))
        
   onView(withId(R.id.more_options_tray)
       .check(matches(hasFocus())))
}

```

We could also check to make sure the item that is going to gain focus `isFocusable()` as well. 

This is just one example of MANY different accessibility regression tests that are possible:

* Label does not include "Heading", "Button", "Link"
  * Ensuring proper roles are used for navigation
* Proper accessible states announced
  * Example: accordion
* Proper grouping of content
  * Ensure content is grouped properly for ease of use
* Keyboard accessibility
  * Ensuring content has proper attributes for keyboard use
* Proper hiding of background content


## Conclusion 

As you can see, building UI tests for accessibility using Espresso is a no brainer. Adding UI tests with accessibility allows your Android accessibility team to: 

* Enforce accessible coding practices
* Help build the importance of a11y on your dev team
* Build a culture of accessibility learning
* Shape definition of done

The only question now is, when will you start adding accessibility test cases?!