Os aplicativos mobile podem ajudar as pessoas a realizar tarefas diárias. No entanto, pessoas com deficiência podem enfrentar várias barreiras ao usar os recursos desses dispositivos se eles não fornecerem acessibilidade adequada. Desenvolvedores de software desempenham um papel crucial na promoção de melhorias de acessibilidade digital, e os testes automatizados podem ajudá-los.
Este tutorial visa abordar esses desafios e capacitar profissionais de desenvolvimento, design e teste para enfrentar as complexidades da acessibilidade em soluções mobile. Com foco em aplicativos Android nativos, exploraremos abordagens e ferramentas para testar e melhorar a acessibilidade. Ao final do tutorial, você será capaz de criar aplicativos com acessibilidade.
Serão apresentadas três alternativas de ferramentas disponíveis para auxiliar a realização de testes de acessibilidade em aplicativos Android nativos. Você será guiado a identificar problemas de acessibilidade em um aplicativo de exemplo – um app Contador – com cada uma das ferramentas apresentadas.
Serão utilizadas as seguintes ferramentas:
Para cada ferramenta, serão fornecidas as instruções passo-a-passo para preparação, configuração, escrita dos testes (quando aplicável), execução e visualização dos resultados. Ao final também haverá um passo-a-passo para solucionar os problemas encontrados e re-executar os testes.
Não é necessário nenhum conhecimento prévio sobre acessibilidade ou testes automatizados para realizar este codelab. No entanto, assumimos que você:
Ao realizar este codelab, você será capaz de:
Neste codelab, você trabalhará com um aplicativo existente, o Contador, derivado do Google Codelabs. Este aplicativo permite aos usuários rastrear, incrementar e decrementar uma contagem numérica. Embora o aplicativo seja simples, você descobrirá que ele tem alguns problemas de acessibilidade que podem dificultar que usuários com deficiência interajam com ele.
Você pode obter o código-fonte da versão inicial do aplicativo neste link.
Você será orientado a executar testes de acessibilidade para identificar esses problemas com cada uma das três ferramentas apresentadas neste tutorial. Para isso, você pode, de acordo com suas habilidades e preferências, escolher entre as seguintes opções:
Para simplificação deste tutorial, iremos considerar apenas a primeira opção.
https://github.com/AALT-Framework/poor-accessibility-apps/Exemplo em Linux
git clone https://github.com/AALT-Framework/poor-accessibility-apps/
cp -r poor-accessibility-apps/Contador Contador-AccessibilityScanner
cp -r poor-accessibility-apps/Contador Contador-Espresso
cp -r poor-accessibility-apps/Contador Contador-AATK
      O Scanner de acessibilidade (Accessibility Scanner) é uma ferramenta criada pelo Google para sugerir melhorias de acessibilidade em apps Android, como aumento de áreas de toque pequenas, aumento de contraste e descrições de conteúdo. Elas possibilitam que pessoas com deficiência possam usar os apps com mais facilidade.

O Scanner de acessibilidade cria um botão de ação flutuante (FAB, na sigla em inglês) azul que fica sobreposto ao conteúdo na tela.

Você pode tocar no FAB para iniciar uma verificação de acessibilidade. Faremos isso daqui a pouco. Para mover o FAB para outra área da tela, mantenha-o pressionado e arraste.
Nesta seção, você vai fazer uma auditoria de acessibilidade da tela usando o Scanner de acessibilidade:
O Scanner de acessibilidade tem cinco sugestões para melhorar a acessibilidade do Contador.
O Scanner de acessibilidade recomenda corrigir o contraste de cores na visualização que mostra a contagem atual.
O Scanner sinaliza os rótulos ausentes em ImageButtons - e + , o que impossibilita que usuários de leitores de tela entendam o propósito desses controles.
- e + e leia as sugestões relacionadas aos rótulos ausentes.Além dos rótulos ausentes, o Scanner sugere aumentar a área de toque dos botões - e +.
No Contador, o contraste de cor é simples de melhorar. A TextView que mostra a contagem usa um plano de fundo cinza-claro com texto cinza:
<TextView
   ...
   android:background="@color/lightGrey"
   android:textColor="@color/grey"
   ...
 />
Você pode remover o plano de fundo, escolher outro mais claro ou deixar o texto mais escuro. Neste codelab, vamos escolher uma cor mais escura para o texto. Veja algumas cores que foram definidas em colors.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   ...
   <color name="lightGrey">#EEEEEE</color>
   <color name="grey">#999999</color>
   <color name="darkGrey">#666666</color>
</resources>
Abra res/layout/activity_main.xml e mude android:textColor="@color/grey" para android:textColor="@color/darkGrey":
<TextView
   ...
   android:background="@color/lightGrey"
   android:textColor="@color/darkGrey"
   ...
 />
Agora, execute o app e veja o contraste melhorado:
Antes  | Depois  | 
  | 
  | 
A proporção de contraste agora é de 4.94:1, consideravelmente melhor que 2.45:1, que é o que tínhamos antes:
Contexto  | Cor do texto  | Taxa de contraste  | |
Antes  | #EEEEEE  | Cinza-claro (#999999)  | 2.45:1  | 
Depois  | #EEEEEE  | Cinza-escuro (#666666)  | 4.94:1  | 
Pressione o FAB para iniciar outra verificação no Scanner de acessibilidade. Você verá que o app não tem mais sugestões relacionadas ao contraste de cor.
Como - e + ImageButtons não têm rótulos, um leitor de tela como o TalkBack não consegue comunicar adequadamente a semântica das visualizações para o usuário, anunciando simplesmente "Botão sem rótulo" quando um botão é focado.
Para corrigir esse problema, atribua uma android:contentDescription para cada botão:
<ImageButton
   android:id="@+id/subtract_button"
   ...
   android:contentDescription="@string/decrement" />
<ImageButton
   android:id="@+id/add_button"
   ...
   android:contentDescription="@string/increment" />
Use strings localizadas nas descrições de conteúdo. Assim, elas poderão ser adequadamente traduzidas. Para este codelab, as strings já foram definidas em res/values/strings.xml.
Agora, um leitor de tela pode anunciar o valor da contentDescription fornecida (adequadamente traduzida para o idioma local) quando o usuário foca nos botões.
Execute o Scanner de acessibilidade novamente. Não há mais sugestões relacionadas a rótulos ausentes.
O Scanner de acessibilidade continua sugerindo que os botões - e + precisam ter uma área de toque maior. Nesta etapa, seguiremos essa sugestão.
Os dois botões no Contador são pequenos (24dp x 24dp). No geral, o tamanho adequado para a área de toque de itens focáveis precisa ser, pelo menos, de 48dp x 48dp. Se for possível criar uma área ainda maior, melhor. Ao aumentar a área de toque de 24dp x 24dp para 48dp x 48dp, ela é expandida por um fator de 4.
Você tem várias opções para aumentar a área de toque dos botões. Por exemplo, você pode escolher uma destas opções:
minWidth e/ou minHeight (os ícones ficarão maiores).Adicione um pouco de padding a cada visualização:
<ImageButton
   ...
   android:padding="@dimen/icon_padding"
   ... />
<ImageButton
   ...
   android:padding="@dimen/icon_padding"
  ... />
O valor de @dimen/icon_padding está definido como 12dp (veja res/dimens.xml). Quando o padding é aplicado, a área de toque do controle se torna 48dp x 48dp (24dp + 12dp em cada direção).
Execute o app novamente para confirmar os novos limites de layout. Agora, a área de toque dos botões é maior.
Execute o Scanner de acessibilidade novamente. Desta vez, a análise será concluída sem sugestões.
Navegue para Configurações > Acessibilidade e defina o Scanner de acessibilidade como Desativado.
O Espresso é um framework de teste de interface do usuário para aplicativos Android, permitindo que os desenvolvedores criem testes automatizados para interagir com os elementos da interface do usuário do aplicativo. É integrado com o Android Studio e pode ser executado em dispositivo físico ou emulado.
Para testar acessibilidade com o Espresso, é possível usar a API AccessibilityChecks do Framework de Testes de Acessibilidade (ATF, na sigla em inglês).
Algumas das checagens realizadas pelo ATF incluem:
No Android Studio, abra o projeto do aplicativo Contador, da pasta Contador-Espresso criada no 2º passo deste treinamento.
Você precisará de uma nova dependência para o pacote androidTestImplementation. Confira se a linha seguinte já foi adicionada para você no arquivo app/build.gradle.
build.gradle da raíz, adicionando a seguinte linha na lista de dependencias.  
dependencies {
    ...
    androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.3.0-alpha05'        
    ...
}

com.example.contador (androidTest).MainActivityInstrumentedTest. Assim você saberá que esta classe de teste instrumentado se refere à MainActivity.Com a classe MainActivityInstrumentedTest gerada e aberta, crie seu primeiro teste. Para o propósito deste codelab, será escrito apenas um único teste, que verifica se o código para incrementar a contagem funciona corretamente (por questões de brevidade, o teste para decrementar a contagem foi omitido). Sua classe deverá ficar assim:
public class MainActivityInstrumentedTest {
    @Rule
    public ActivityScenarioRule<MainActivity> mActivityTestRule = new ActivityScenarioRule<>(MainActivity.class);
    @Test
    public void testIncrement(){
        Espresso.onView(withId(R.id.add_button))
            .perform(ViewActions.click());
        Espresso.onView(withId(R.id.countTV))
            .check(matches(withText("1")));
    }
}
Primeiro, verifique se o seu computador está conectado a um dispositivo com a depuração USB ativada.
Agora execute os testes clicando no botão de seta verde imediatamente à esquerda de @Test public void testIncrement(). Se você estiver usando um dispositivo físico conectado via USB, certifique-se de que o dispositivo esteja desbloqueado e com a tela ligada. Observe que pressionar Ctrl+Shift+F10 (Control+Shift+R em um Mac) executa os testes no arquivo atualmente aberto.
O teste deve ser executado até o final e deve passar, confirmando que o incremento da contagem funciona como esperado.
Na próxima seção, você irá modificar o teste para verificar também a acessibilidade.
Com o Espresso, você pode habilitar verificações de acessibilidade chamando AccessibilityChecks.enable() de um método de configuração. Adicionar essa única linha de código permite que você teste sua interface do usuário para acessibilidade, tornando fácil integrar a verificação de acessibilidade em seu conjunto de testes.
Para configurar a classe MainActivityInstrumentedTest para checagens de acessibilidade, adicione o seguinte método de configuração antes do seu teste.
    @BeforeClass
    public static void beforeClass()
    {
        AccessibilityChecks.enable();
    }
Agora execute o teste novamente. Desta vez, você perceberá que o teste falha. No painel Run, clique duas vezes em testIncrement para ver os resultados. Você notará a mensagem de erro.
O teste falhou porque o ATF encontrou duas oportunidades para melhorar a acessibilidade do aplicativo:
ImageButton de adição (+) contém uma imagem, mas não tem um rótulo. Ele precisa de um rótulo para que um usuário de leitor de tela possa entender o propósito do botão.ImageButton também precisa de um alvo de toque maior para que os usuários com destreza manual limitada possam interagir com o botão com mais facilidade.Nesta etapa, você fará alterações no arquivo res/layout/activity_main.xml para atender às sugestões do ATF que estão causando falhas nos seus testes (lembre-se de que o ATF encontrou duas oportunidades para melhorar a acessibilidade, incluindo um rótulo e o aumento do tamanho do alvo de toque):
Primeiro, você irá adicionar um rótulo ao botão de adicionar.
Abra o arquivo res/layout/activity_main.xml e procure o código do primeiro ImageButton (você notará um aviso do lint sobre a falta de contentDescription):
    <ImageButton 
        android:id="@+id/subtract_button"
        ...
        android:contentDescription="@string/decrement" />
    <ImageButton
        android:id="@+id/add_button"
        ...
        android:contentDescription="@string/increment" />
Use strings localizadas nas descrições de conteúdo. Assim, elas poderão ser adequadamente traduzidas. Para este codelab, as strings já foram definidas em res/values/strings.xml.
Execute o teste novamente e você não verá mais uma falha relacionada ao rótulo do botão.
Agora você irá abordar a outra recomendação do ATF, que se refere ao tamanho do alvo de toque do botão. O tamanho de toque para o botão é de 24x24dp, e a mensagem de falha do teste indica que o tamanho de toque mínimo recomendado é de 48x48dp.
Você tem várias opções para aumentar a área sensível ao toque dos botões. Por exemplo, você pode fazer o seguinte:
Em res/layout/activity_main.xml, podemos ver as seguintes definições para os dois botões:
    <ImageButton
        android:id="@+id/add_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ... />
    <ImageButton
        android:id="@+id/subtract_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ... />
Adicione um pouco de padding a cada visualização:
    <ImageButton
        ...
        android:padding="@dimen/icon_padding"
        ... />
    <ImageButton
        ...
        android:padding="@dimen/icon_padding"
        ... />
O valor de @dimen/icon_padding está definido como 12dp (veja res/dimens.xml). Quando o padding é aplicado, a área de toque do controle se torna 48dp x 48dp (24dp + 12dp em cada direção).
Execute o teste novamente. A falha do teste relacionada aos alvos de toque não ocorre mais, portanto o teste é aprovado.
Todas as verificações de acessibilidade que você encontrou até agora estavam associadas ao botão "adicionar", que é a visualização na qual você executou uma ação de visualização. Agora você configurará seus testes para examinar outras visualizações na hierarquia, sem precisar executar ações adicionais de visualização nessas visualizações.
Usando o objeto AccessibilityValidator, você pode chamar setRunChecksFromRootView(true) para obter uma cobertura expandida de acessibilidade, verificando toda a hierarquia de visualização em cada ação de visualização.
Modifique seu método enableAccessibilityChecks() da seguinte forma:
    @BeforeClass
    public static void beforeClass()
    {
        AccessibilityChecks.enable()
            .setRunChecksFromRootView(true);
    }
Execute os testes novamente. Desta vez, o teste falhará com a seguinte mensagem de erro:
...
There was 1 accessibility error:
AppCompatTextView{id=-1, ...}: TextView does not have required contrast of 3.000000. Actual contrast is 2.455571
at ...
O texto e o plano de fundo da visualização devem ter um contraste de cor maior. Ao definir setRunChecksFromRootView(true), você encontrou mais oportunidades para melhorar a acessibilidade do seu aplicativo.
Melhore o contraste de cor para o TextView do contador, alterando a cor do texto de @color/grey para @color/darkGrey.
    <TextView
        ...
        android:textColor="@color/darkGrey"
        ... 
    />
Agora execute o teste novamente. Com o cinza mais escuro, o texto do contador tem mais contraste de cor com o fundo, então o ATF não deve fazer nenhuma sugestão de acessibilidade. O teste deve executar com sucesso até o final.
Os aplicativos mobile podem ajudar as pessoas a realizar tarefas diárias. No entanto, pessoas com deficiência podem enfrentar várias barreiras ao usar os recursos desses dispositivos se eles não fornecerem acessibilidade adequada.
Os desenvolvedores de software desempenham um papel crucial na promoção de melhorias de acessibilidade digital, e os testes automatizados podem ajudá-los.
O Kit de Testes de Acessibilidade Automatizados para Aplicativos Android (AATK) consiste em uma coleção de testes de acessibilidade automatizados projetados para serem executados com o Robolectric. Isso permite que sejam executados como testes locais, sem a necessidade de um dispositivo físico ou emulado.
Este kit foi desenvolvido com foco nos problemas de acessibilidade mais comuns e nos widgets mais usados, onde muitos problemas de acessibilidade tendem a ocorrer.
No Android Studio, abra o projeto do aplicativo Contador, da pasta Contador-AATK, criada no 2º passo deste treinamento.
Siga os seguintes passos para preparar o projeto para adicionar testes de acessibilidade automatizados:
settings.gradle da raíz, adicionando maven { url 'https://jitpack.io' } na lista de repositories.  
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
build.gradle no nível do aplicativo para habilitar a execução de testes com o Robolectric e o AATK, atualizando os testOptions e adicionando as dependências necessárias.  
Primeiro, adicione a diretiva testOptions com as seguintes linhas, dentro da diretiva android, assim:android{
    ...
    testOptions {
        // Usado para testar elementos dependentes do Android na pasta de teste
        unitTests.includeAndroidResources  = true
        unitTests.returnDefaultValues = true
    }
}
Em seguida, adicione estas duas dependências como testImplementation:dependencies {
    ...
    testImplementation 'org.robolectric:robolectric:4.9'
    testImplementation 'com.github.AALT-Framework:android-accessibility-test-kit:v1.0.0-alpha'
    ...
}
com.example.contador (test).MainActivityTest. Assim você saberá que esta classe de teste se refere à MainActivity.Com a classe MainActivityTest gerada e aberta, comece a configurá-la para executar os testes AATK.
Sua classe deverá ficar assim:
@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {
    private View rootView; // Raiz da hierarquia de exibição
    private AccessibilityTestRunner runner; // Runner de testes de acessibilidade
    @Rule
    public ErrorCollector collector = new ErrorCollector(); // Coletor de erros
    @Before
    public void setUp() {
        // Crie uma instância da atividade
        MainActivity activity = Robolectric.buildActivity(MainActivity.class).create().get();
        // Obtenha a view raiz da hierarquia de exibição
        rootView = activity.getWindow().getDecorView().getRootView();
        runner = new AccessibilityTestRunner(collector);
    }
}
O que foi feito:
RoboletricTestRunner.AccessibilityTestRunner.ErrorCollector.setUp da seguinte para habilitar que o kit seja executado em qualquer novo texte criado.Adicione um método de teste para cada teste de acessibilidade que deseja executar. Começaremos com a verificação da taxa de contraste de cores.
Uma taxa de contraste adequada ajuda os usuários a identificar melhor o conteúdo do aplicativo. Uma relação de contraste de pelo menos 4,5:1 deve ser usada.
Você pode utilizar o teste de taxa de contraste do AATK (TestAdequateContrastRatio) da seguinte forma:
    @Test
    public void deve_UsarTaxaDeContrasteAdequada(){
        runner.runAccessibilityTest(rootView, new TestAdequateContrastRatio());
    }
deve_UsarTaxaDeContrasteAdequada para ver os resultados. Você notará a mensagem de erro, a identificação View, a taxa esperada e a taxa atual.  
res/layout/activity_main.xml, encontre o TextView e altere android:textColor="@color/grey" para android:textColor="@color/darkGrey".  
Agora que já criou seu primeiro teste, você pode adicionar outros. A seguir, iremos sugerir mais dois exemplos. Consulte a documentação do AATK para consultar todos os testes disponíveis.
Todo conteúdo não textual deve ter uma descrição de texto alternativa. Isso permite que um leitor de tela possa identificar corretamente o conteúdo.
Para esse teste, você irá utilizar o teste de texto alternativo do AATK (TestMustHaveAlternativeText), assim como fez para o teste de contraste.
    @Test
    public void deve_ConterAlternativaTextual(){
        runner.runAccessibilityTest(rootView, new TestMustHaveAlternativeText());
    }
Todos os elementos de interação devem ter no mínimo 48x48dp.
Para esse teste, você irá utilizar o teste de texto alternativo do AATK (TestTouchTargetSize), assim como fez para os testes anteriores.
deve_AlvoDeToquePossuirTamanhoMinimorunAccessibilityTest do executor do kit, passando como parâmetro a view raíz e uma nova instância do teste desejado.    @Test
    public void deve_AlvoDeToquePossuirTamanhoMinimo(){
        runner.runAccessibilityTest(rootView, new TestTouchTargetSize());
    }
Obrigado por sua participação!