Android

16 jun, 2015

Automatizando testes funcionais no Android com Calabash

Publicidade

No artigo anterior, comentei os conceitos principais de BDD e Cucumber, que são importantíssimos para acompanhar esse segundo texto. Nele também falei sobre a configuração inicial da máquina, explicando como instalar o Ruby e o Calabash.

Antes de iniciar o desenvolvimento dos testes, é preciso que você já tenha instalado em sua máquina o Android SDK. Caso precise instalá-lo, veja as informações presentes neste link. Se preferir, você pode instalar o Android Studio, mas ele não será necessário para a realização dos testes, pois executaremos somente o apk. Você também vai precisar de um emulador aberto ou um device conectado para que os testes sejam executados.

Agora, com nosso ambiente configurado, vamos iniciar o desenvolvimento dos nossos testes. Primeiro, precisamos definir um aplicativo a ser testado. O Victor Nascimento, aqui da nossa equipe, gentilmente disponibilizou em seu GitHub um aplicativo bem simples, que recebe como parâmetro um CEP e exibe na tela o resultado da consulta desse valor em uma API dos Correios. Por favor, clone esse repositório e acesse-o pelo terminal. Execute o comando ./gradlew assembleDebug para compilar esse projeto.

Ao final do comando, teremos gerado um apk para esse projeto, que pode ser encontrado na pasta CaminhoPastaProjeto/app/build/outputs/apk/app-debug.apk. Guarde com cuidado esse caminho, pois será necessário quando formos executar os testes utilizando o Calabash.

A gem calabash-android possui um gerador para facilitar o início do desenvolvimento dos testes. Para executá-lo, abra o terminal e navegue até uma pasta qualquer. Essa pasta será a raiz do nosso projeto de testes e pode estar em qualquer lugar da sua máquina, podendo ser inclusive a pasta raiz do projeto consultaCEP.

Dentro dessa pasta, digite o comando calabash-android gen. Esse comando irá gerar a pasta features, que conterá alguns arquivos de exemplo e alguns arquivos de configuração. O conteúdo da pasta gerada pode ser visto na figura abaixo.

figura1

Vamos aproveitar esses arquivos gerados para criar os nossos testes. Em seu editor de textos preferido, abra o arquivo features/my_first.feature.

Vamos apagar todas as linhas desse arquivo e substituí-las pelas abaixo:

# language: pt
Funcionalidade: Consultar CEP

Vale destacar que a língua padrão do Cucumber (responsável por interpretar o arquivo de features) é o inglês. Porém, ele aceita mais de 40 outras línguas, inclusive o português (consulte as línguas aqui). Para o português ou qualquer outra língua não padrão, deve-se adicionar um comentário na primeira linha, como pode ser visto no código acima.

Agora vamos escrever o nosso primeiro cenário. Nele, vamos testar a funcionalidade que realiza uma consulta a um determinado CEP.

# language: pt
Funcionalidade: Consultar CEP

Cenário: Posso consultar um CEP
Dado que estou na tela inicial
Quando digitar um CEP
E clicar no botão consultar
Então devo ver o nome da rua na tela

Agora que temos nosso primeiro cenário, precisamos codificar as ações de cada um dos passos que compõem o cenário. Para isso, precisamos criar as expressões regulares responsáveis por identificar unicamente esses passos. Não precisamos nos preocupar em saber a fundo como criar expressões regulares, pois aos executar os testes o próprio Cucumber irá sugerir uma forma de interpretar os passos.

Então vamos lá: execute no terminal o comando abaixo. Lembre-se, você deve estar dentro da pasta do projeto (pasta onde executou o comando de geração do calabash-android):

calabash-android run caminho_do_apk

A saída apresentada pelo comando será algo como:

No test server found for this combination of app and calabash version. Recreating test server.
Done signing the test server. Moved it to test_servers/e5b89812e18ef46ab1f9d1fb84fbbe72_0.5.5.apk

app-debug.apk
# language: pt
Funcionalidade: Consultar CEP

  Cenário: Posso consultar um CEP        # features/my_first.feature:4
354 KB/s (557671 bytes in 1.536s)
1781 KB/s (348895 bytes in 0.191s)
    Dado que estou na tela inicial       # features/my_first.feature:5
    Quando digitar um CEP                # features/my_first.feature:6
    E clicar no botão consultar          # features/my_first.feature:7
    Então devo ver o nome da rua na tela # features/my_first.feature:8

1 scenario (1 undefined)
4 steps (4 undefined)
0m11.547s

You can implement step definitions for undefined steps with these snippets:

Dado(/^que estou na tela inicial$/) do
  pending # express the regexp above with the code you wish you had
end

Quando(/^digitar um CEP$/) do
  pending # express the regexp above with the code you wish you had
end

Quando(/^clicar no botão consultar$/) do
  pending # express the regexp above with the code you wish you had
end

Então(/^devo ver o nome da rua na tela$/) do
  pending # express the regexp above with the code you wish you had
end

Logo no início, o Calabash informa que esse aplicativo nunca havia sido utilizado para um teste e portanto precisa que o ‘Test Server’ do Calabash seja incluído nesse apk. Isso é feito automaticamente. Logo depois, serão exibidos a Funcionalidade e o Cenário que será executado. Os números seguidos pela unidade KB/s representam a instalação do apk no emulador. Depois, são apresentados os passos a serem executados. Por fim, é mpstrado um pequeno resumo da execução, em que pode-se ver que um cenário e quatro passos foram executados e que todos eles estão indefinidos.

Logo após o resumo, o Cucumber sugere uma implementação para cada um dos passos indefinidos encontrados no arquivo de Funcionalidade. Para agilizar o desenvolvimento, vamos aceitar essas sugestões. Portanto, copie-as para o arquivo features/step_definitions/calabash_steps.rb.

Se executarmos novamente os testes, veremos que ao invés de estarem indefinidos, agora eles estão pendentes. Isso ocorre por causa da palavra pending presente em todos os passos. Essa palavra reservada lança uma “exceção” que indica para o Cucumber que a implementação daquele passo está pendente.

Vamos agora “preencher” nossos passos. Para o primeiro, temos:

Dado(/^que estou na tela inicial$/) do
  wait_for(timeout: 5) { element_exists "* id:'input_cep'" }
end

Nesse passo, esperamos até cinco segundos para que um determinado elemento exista. Nesse caso, estamos esperando o elemento ‘input_cep’, que é o campo TextField que receberá o valor do CEP.

No Calabash, para que possamos acessar determinados elementos da tela, devemos utilizar uma forma específica de string de consulta. No caso, a string “* id:’input_cep'” determina que deve-se procurar na tela qualquer (*) tipo de elemento Android (classe, botão, label, text field), cujo id seja igual à string ’input_text’. Após cinco segundos, caso o elemento não seja encontrado, uma exceção é lançada e o teste falha.

Execute o teste e veja que o primeiro passo é executado sem problemas (indicado pela cor verde), porém, agora, é o segundo que falha por causa do pending. Sendo assim, vamos implementar o segundo passo:

Quando(/^digitar um CEP$/) do
  query "* id:'input_cep'", { setText: "04565001" }
end

Nesse passo, realizamos uma consulta ao elemento input_cep e atribuímos um valor por meio da função :setText. Nesse caso, estamos inserindo o CEP da Concrete Solutions para buscar o nome da rua à qual esse CEP corresponde.

Sempre que um passo é implementado, é bom garantir que ele passe. Então vamos lá, execute novamente os testes e veja os dois primeiros passos passarem. Para o terceiro passo, temos:

Quando(/^clicar no botão consultar$/) do
  touch "* id:'botao_consulta'"
end

Nesse passo, utilizamos uma função especial do Calabash chamada touch. Como o nome indica, essa função é responsável por clicar no elemento definido pela string de consulta passada como parâmetro. Novamente, execute o teste e veja os passos passarem. Vamos para a implementação do nosso último passo:

Então(/^devo ver o nome da rua na tela$/) do
  wait_for(timeout: 5) { element_exists "* {text CONTAINS 'Rua Flórida'}" } 
end

Nesse passo, esperamos até cinco segundos para ver na tela qualquer tipo de elemento que possua, dentro de um de seus atributos, uma string que contenha o conjunto de caracteres ’Rua Flórida’.

Finalmente, execute seus testes e veja todos os passos passarem.

Com isso, terminamos de testar nosso primeiro cenário da funcionalidade de consulta CEP. Existem outros cenários que poderiam ser implementados, como o Histórico. Um desafio: tente implementar esse cenário, no qual deve-se tocar o botão ‘OK’ apresentado após a consulta do CEP e realizar uma nova consulta de CEP. Como todas as consultas são armazenadas na tela, avalie no final do cenário se todas as ruas consultadas aparecem na tela. Se tiver problemas, por favor, poste nos comentários.

Antes de encerrar, vou passar uma dica. Durante o desenvolvimento dos testes, caso você não tenha acesso ao código fonte do apk e, com isso, não saiba quais os ID dos elementos ou caso deseje testar alguma função para ver se ela se comporta como esperado, utilize o console do Calabash. Esse console permite que você digite funções que são interativamente executadas no simulador.

Para abrir o Calabash console, execute o seguinte comando no terminal:

calabash-android console caminho_do_apk

Logo após sua execução, execute os dois comandos abaixo:

reinstall_apps
start_test_server_in_background

O primeiro comando irá instalar/reinstalar o aplicativo no emulador ou device conectado. O segundo irá iniciar o servidor de testes, bem como o aplicativo. Assim que o segundo comando terminar de executar, já é possível digitar os comandos a serem executados pelo Calabash.

Um comando bastante interessante é o query “*”. Esse comando irá retornar todos os elementos presentes na tela em um formato parecido com o do XML. A partir desse retorno, podemos analisar os IDs de todos os elementos da tela, descobrindo, assim, como podemos identificá-los para que possamos interagir com eles sem a necessidade de conhecer o código-fonte.

Com isso, chegamos ao fim do nosso artigo. Fique atento para o próximo, no qual falarei sobre como utilizar o Calabash para automatizar também os testes funcionais no iOS. A pasta features gerada pelo Calabash, bem como os passos implementados durante o texto podem ser encontrados no meu GitHub.