Experiência na implementação de automação no processo de teste manual no exemplo de um aplicativo Android

Um bom testador com habilidades de pensamento crítico não pode ser completamente substituído pela automação. Tornar o trabalho mais eficiente é fácil. Com essa convicção, fui ao nosso departamento de testes com uma nova tarefa, onde nós, juntamente com Pavel, assumimos sua implementação. Vamos ver o que aconteceu.

Juntamente com nossos parceiros, estamos ativamente desenvolvendo, testando e dando suporte a uma família de aplicativos para diferentes plataformas: Android, iOS, Windows. Os aplicativos estão se desenvolvendo ativamente, juntamente com os quais o volume de testes está aumentando, principalmente a regressão.

Decidimos tentar facilitar e acelerar o teste automatizando a maioria dos casos de teste. Ao mesmo tempo, não queríamos abandonar completamente o processo de teste manual, mas modificá-lo.

A implementação dessa abordagem começou com um dos aplicativos Android, sobre o qual falarei. O artigo será de interesse para autores iniciantes de testes de interface do usuário, principalmente para aplicativos móveis, bem como aqueles que desejam automatizar o processo de teste manual até certo ponto.

Vamos lá!

Ponto de partida


Para cada plataforma, temos várias similares que executam o mesmo processo de negócios principal de aplicativos. No entanto, eles diferem um do outro em um conjunto de pequenas funcionalidades auxiliares, são feitas sob marcas diferentes, dependendo do cliente (devido ao qual a interface muda de aplicativo para aplicativo), e o processo de negócios pode ser personalizado adicionando etapas adicionais.

Estamos diante de certos problemas que precisam ser abordados. Dificuldades semelhantes podem surgir em uma situação diferente da nossa. Por exemplo, se você tiver um aplicativo volumoso com lógica comercial difícil, cheio de muitos testes.

Problema # 1: muitos testes de regressão


Os conjuntos de cenários de teste para cada aplicativo são simultaneamente semelhantes e diferentes entre si, o que contribui para um aumento na regressão e a torna ainda mais chata. No entanto, você precisa testar todos os aplicativos individualmente.

Considerando que os aplicativos já em execução são atualizados regularmente e, no futuro, haverá apenas mais, o número total de testes aumentará inexoravelmente.

Problema número 2: você precisa testar em todas as versões do sistema operacional móvel


Um requisito importante é a disponibilidade de nossos aplicativos móveis em uma ampla variedade de versões de sistemas operacionais. Por exemplo, no caso do Android no momento da escrita, esses são níveis de API de 17 a 28.

Idealmente, devemos testar em cada versão do Android, o que complica ainda mais nossa regressão. O processo de teste direto do aplicativo adquire uma rotina adicional multiplicada pelo número de dispositivos: instalação e execução do aplicativo, trazendo-o ao seu estado original após cada remoção individual de teste. Ao mesmo tempo, a manutenção de seu próprio farm de dispositivos exige bastante trabalho.

Solução: integre a automação ao processo de teste manual



Uma tarefa típica da automação de teste é automatizar testes de regressão. Então, queremos melhorar a eficiência do processo de teste hoje e evitar as possíveis conseqüências do crescimento amanhã.

Ao mesmo tempo, estamos cientes de que é impossível e desnecessário erradicar completamente os testes manuais por automação. O pensamento crítico e o olho humano são difíceis de substituir por algo. Há um bom artigo sobre esse assunto no blog de Michael Bolton, The End of Manual Testing (ou tradução de Anna Rodionova).

Nós pensamos que seria útil ter um conjunto de testes automatizados que cobrissem as partes estáveis ​​do aplicativo e, no futuro, escrevesse testes para erros encontrados e novas funcionalidades. Ao mesmo tempo, queremos associar os autotestes aos conjuntos de testes existentes em nosso sistema de gerenciamento de testes (usamos o TestRail) e também permitir que os testadores executem facilmente autotestes em dispositivos físicos na nuvem (escolhemos o Firebase Test Lab como a infraestrutura na nuvem).

Para começar e tentar, pegamos um de nossos aplicativos Android. Era importante considerar que, se a solução fosse bem-sucedida, suas práticas recomendadas poderiam ser aplicadas a outros aplicativos, inclusive em outras plataformas.

O que queremos obter como resultado:

  1. Automação de testes de regressão.
  2. Integração com o sistema de gerenciamento de testes.
  3. Possibilidade de início manual parametrizado de autoteste em dispositivos na nuvem.
  4. A possibilidade de reutilizar a solução no futuro.

A seguir, falarei separadamente sobre a implementação de cada um desses pontos com um pouco de imersão no componente técnico.

Esquema geral de implementação da solução


Mas primeiro, um esboço geral do que obtivemos:

imagem

Os testes automáticos são executados de duas maneiras:

  1. Do IC após mesclar ou puxar solicitação para mestre.
  2. Teste manualmente a partir da interface da web do Jenkins Job.

No caso de uma inicialização manual, o testador deve indicar o número da compilação correspondente ou fazer o download de 2 APKs no computador: com o aplicativo e com os testes. Este método é necessário para que você possa executar os testes necessários a qualquer momento em qualquer dispositivo disponível.

Durante os testes, seus resultados são enviados para o TestRail. Isso acontece da mesma maneira como se o testador executasse o teste manualmente e inserisse os resultados de uma maneira familiar a ele.

Assim, deixamos o processo estabelecido de teste manual, mas adicionamos automação a ele, que executa um conjunto específico de testes. O testador "capta" o que foi feito automaticamente e:

  • vê o resultado de casos de teste em cada dispositivo que foi selecionado;
  • pode verificar manualmente qualquer caso de teste;
  • executa casos de teste que ainda não foram automatizados ou que não podem ser otimizados por qualquer motivo;
  • toma a decisão final no teste atual.

Agora vamos para a descrição prometida da implementação.

1. Auto testes


As ferramentas


Usamos três ferramentas para interagir com a interface do usuário:

  • Espresso
  • Barista.
  • UI Automator.

A principal ferramenta e a que começamos é o Espresso. O principal argumento a favor de sua escolha foi o fato de o Espresso permitir que você teste usando o método da caixa branca, fornecendo acesso à Instrumentação Android. O código de teste está no mesmo projeto que o código do aplicativo.

O acesso ao código do aplicativo Android é necessário para chamar seus métodos nos testes. Podemos preparar nosso aplicativo para um teste específico com antecedência, executando-o no estado correto. Caso contrário, precisamos atingir esse estado através da interface, que priva os testes de atomicidade, tornando-os dependentes um do outro, e simplesmente consome muito tempo.

Durante a implementação, outra ferramenta foi adicionada ao Espresso - UI Automator. Ambas as estruturas fazem parte da Biblioteca de suporte a testes do Google, do Google . Usando o UI Automator, podemos interagir com várias caixas de diálogo do sistema ou, por exemplo, Gaveta de Notificações.

E o último em nosso arsenal foi o quadro Barista. É um invólucro do Espresso, economizando o código padrão ao implementar ações comuns do usuário.

Tendo em mente o desejo de poder reutilizar a solução em outros aplicativos, é importante observar que as ferramentas listadas destinam-se exclusivamente a aplicativos Android. Se você não precisar acessar o código do aplicativo em teste, provavelmente preferirá usar uma estrutura diferente. Por exemplo, o Appium muito popular hoje. Embora você também possa tentar acessar o código do aplicativo com a ajuda de backdoors, é um bom artigo no blog do Badoo. A escolha é sua.

Implementação


Como padrão de design, escolhemos o Testing Robots, proposto por Jake Wharton no relatório homônimo. A idéia dessa abordagem é semelhante ao padrão de design de objeto de página comum usado no teste de sistemas da web. A linguagem de programação é Java.

Para cada fragmento independente do aplicativo, é criada uma classe de robô especial na qual a lógica de negócios é implementada. A interação com cada elemento do fragmento é descrita em um método separado. Além disso, todas as asserções realizadas neste fragmento também são descritas aqui.

Considere um exemplo simples. O fragmento descrito contém vários campos para inserir dados e um botão de ação:

imagem

O código da funcionalidade de login é o próprio teste:

imagem

Aqui, verificamos o cenário positivo quando os dados de autenticação inseridos estão corretos. Os dados em si são submetidos aos testes de entrada ou os valores padrão são usados. Assim, o testador tem a capacidade de parametrizar em termos de dados de teste.

Essa estrutura fornece, em primeiro lugar, excelente legibilidade aos testes quando todo o script é dividido nas principais etapas de execução. Também gostamos muito da ideia de transferir afirmações para os métodos individuais do robô correspondente. A afirmação se torna a mesma etapa, sem quebrar a cadeia geral, e seus testes ainda não sabem nada sobre o aplicativo.

No relatório mencionado, Jake Wharton faz uma implementação em Kotlin, onde é finito. Já tentamos em outro projeto e gostamos muito.

2. Integração com o sistema de gerenciamento de testes


Antes da introdução da automação, realizamos todos os nossos testes no sistema de gerenciamento de testes TestRail. A boa notícia foi que existe uma API TestRail bastante boa, com a qual conseguimos conectar casos de teste já estabelecidos no sistema com autotestes.

Durante a execução do teste usando o JUnit RunListener , vários eventos são capturados, como testRunStarted , testFailure , testFinished , nos quais enviamos os resultados para o TestRail. Se você usa o AndroidJUnitRunner, ele precisa informar sobre o seu RunListener de uma certa maneira, descrita na documentação oficial .

Você também precisa se comunicar com várias entidades do TestRail por seu ID. Portanto, para conectar o teste ao caso de teste correspondente, criamos uma anotação simples @CaseId , cujo uso é mostrado no exemplo de implementação de teste acima.

Código para implementar a anotação em si:

imagem

Resta apenas obter seu valor no lugar certo a partir de Descrição:

imagem

3. Início manual de autotestes em dispositivos na nuvem


Parametrização de inicialização no trabalho Jenkins


Para organizar o início manual dos autotestes, usamos o trabalho Jenkins de estilo livre . Essa opção foi escolhida porque a empresa já possuía alguma experiência com trabalhos semelhantes com a Jenkins Job em outras áreas, em particular com os engenheiros do DevOps, que eles compartilharam com prazer.

O trabalho de Jenkins executa um script com base nos dados transferidos da interface da web. Assim, a parametrização das execuções de teste é implementada. No nosso caso, o script Bash inicia o lançamento de testes nos dispositivos em nuvem do Firebase.

A parametrização inclui:

  • Selecionando o APK desejado, especificando o número da compilação correspondente ou fazendo o download manualmente.
  • Digite todos os tipos de dados de teste.
  • Inserindo dados personalizados adicionais para TestRail.
  • Selecione dispositivos físicos baseados na nuvem nos quais os testes serão executados na lista disponível no Firebase Test Lab.
  • A seleção de kits de teste a serem realizados.

Vejamos uma parte da página da Web do nosso trabalho Jenkins usando um exemplo de uma interface de seleção de dispositivo e suítes de teste:

imagem

Cada elemento em que você pode inserir ou selecionar qualquer dado é implementado por plugins Jenkins especiais. Por exemplo, a interface de seleção de dispositivo é feita usando o plug-in de opções ativas . Usando um script groovy do Firebase, é obtida uma lista de dispositivos disponíveis, que são exibidos no formulário desejado na página da web.

Após a inserção de todos os dados necessários, o script correspondente é iniciado, cujo progresso podemos observar na seção Saída do console:

imagem

A partir daqui, o testador que iniciou a execução do teste pode acessar o TestRail ou o console do Firebase usando os URLs recebidos, que contêm muitas informações úteis sobre a execução de testes em cada um dos dispositivos selecionados.

Matriz de teste final no Firebase Test Lab


A matriz do dispositivo no Firebase contém a distribuição de testes pelos dispositivos nos quais eles foram executados:

imagem

Para cada dispositivo, você pode visualizar o registro completo, o vídeo da execução do teste, vários indicadores de desempenho. Além disso, você pode acessar todos os arquivos que podem ter sido criados durante a execução dos testes. Usamos isso para baixar indicadores de cobertura de teste do dispositivo.

Escolhemos o Firebase, pois já usamos esse serviço para solucionar outros problemas e estamos satisfeitos com a política de preços. Se você encontrar 30 minutos de tempo puro para testes por dia, não precisará pagar nada. Esse pode ser um motivo adicional pelo qual é importante poder executar apenas determinados testes.

Você pode preferir uma infraestrutura de nuvem diferente que também se adapte bem ao seu processo de teste.

4. Reutilização


Como tudo isso pode ser usado no futuro? Do ponto de vista da base de código, esta solução é aplicável apenas a aplicativos Android. Por exemplo, durante a implementação, adicionamos as classes auxiliares EspressoExtensions e UiAutomatorExtensions , nas quais encapsulamos várias opções para interagir com a interface e aguardamos que os elementos estejam prontos. Isso também inclui a classe RunListener, responsável pela integração com o TestRail. Já os colocamos em módulos separados e os usamos para automatizar outros aplicativos.

Se falamos de outras plataformas, a experiência adquirida pode ser muito útil para criar e implementar processos semelhantes. Estamos fazendo isso ativamente na área do iOS e estamos pensando no Windows.

Conclusão


Existem muitas opções para implementar e usar a automação de teste. Entendemos que a automação é principalmente uma ferramenta projetada para facilitar o processo tradicional de teste "humano" e não para erradicá-lo.

Source: https://habr.com/ru/post/pt434252/


All Articles