Android Testing 4 — Configuração do ambiente para testes

Dario Mungoi
Google Developer Experts
5 min readJan 3, 2017

--

Viva pessoal, em primeiro lugar gostaria de desejar um feliz ano novo e que este seja repleto de muitas realizações e progresso na carreira como desenvolvedor Android.
Depois ter explicado sobre dependency Injection e como estruturar um model que nos permita efectuar testes e ter um código mais limpo e legível no post anterior, vamos dar continuidade a série e neste post irei mostrar como fazer as configurações necessárias para criar um ambiente que possibilite a escrita e execução de testes unitários no android.

Escrever testes no android tornou-se uma tarefa muito simples devido a criação da “Android Test Support Library” que contém todas as API’s necessárias para fazer testes unitários(Unit Tests), testes instrumentais(Instrumented Tests) entre outras.

Para começar a utilizar esta biblioteca para escrever e executar testes em uma app, basta simplesmente seguir os seguintes passos:

Adicionar as bibliotecas pelo Gradle

Porque neste post irei focar-me apenas nos testes unitários, o primeiro passo para poder utilizar as API’s da biblioteca de suporte será aplicar ao projecto as “dependencies” necessárias no ficheiro build.gradle do modulo “app”.

dependencies {
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
}

A primeira biblioteca e indispensável é o framework de testes JUnit que facilita a criação de código para automação de testes e apresentação dos resultados.
Com o JUnit é possível testar se uma função ( método) esta a funcionar como esperado utilizando um conjunto de métodos para a verificação dos resultados.

A Segunda biblioteca mas não essencial para a criação de testes unitários básicos,é o framework Mockito que em palavras simples permite que se possa utilizar uma versão “Oca”(Sem nenhuma implementação) de algum componente do android que os testes unitários tenham como dependência. (O Mockito só será devidamente utilizado e explicado no próximo post)

Com as bibliotecas devidamente adicionadas ao projecto, o próximo passo é criar um ambiente de hermético que consiste em simplesmente criar um ambiente de testes em que estes são executados de forma isolada a qualquer tipo de dependências.

Exemplo: Para este projecto, apresentar a lista de eventos depende do backend, da conectividade a Internet entre outros factores que podem influenciar nesta tarefa.

Sendo assim, a criação de um ambiente hermético irá permitir que possamos criar implementações falsas destes componentes necessários e utilizar o conceito de dependency injection para Injectar estas implementações as componentes que desejamos testar.
Para atingir este objectivo, poderíamos utilizar bibliotecas de dependency Injection como o Dagger ou a forma mais fácil apresentada neste post que consiste em utilizar a funcionalidade de build flavours disponível no plugin do gradle ao nosso favor.

Criar build flavours

Build flavours é uma funcionalidade disponível no gradle plugin que nos permite criar diferentes versões de uma aplicação que tenham funcionalidades básicas comuns e mais funcionalidades distintas dependendo do fim para que a versão foi criada.

Um exemplo muito clássico é o caso de aplicações com versões pagas e grátis em que as duas tem funcionalidades em comum mas a versão paga costuma ter funcionalidades a mais em relação a versão grátis .

Criar build flavours é muito simples e o primeiro passo a fazer, é definir as versões no gradle como mostra o script abaixo.

android{  //outras configuracoes
productFlavors {
mock {
applicationId "co.app.evently.mock"
versionName "1.0.0"
}
prod{
applicationId "co.app.evently"
versionName "1.0.0"
}
}
}

De seguida é necessário fazer a sincronização do projecto e adicionar directórios como apresentado no esquema abaixo.
Nota:Na criação do projecto, os directórios main,androidTest devem ter sido gerados automaticamente

app(module)
-->src
-->androidTest(contém código dos testes unitários de integração)
-->main (contem código comum entre a versão de testes e produção. Ex: EventListFragment
)
-->mock (contém código da versão exclusivamente para testes)
-->prod (contém código da versão de produção)
-->test (contém código dos testes unitários)

Só é possível trabalhar em um versão de cada vez simplesmente mudando a configuração como mostra a figura abaixo.
Ao escolher uma das versões, o projecto só terá visibilidade dos ficheiros existentes dentro do directório correspondente e os ficheiros do directório main que são comuns independentemente da versão seleccionada.

Com esta funcionalidade é possível criar uma classe Injection em cada uma das versões que disponibilizará uma versão diferente do repositório(explicado no post anterior) consoante a versão selecionada, isto é, dentro da versão mock, a classe Injection terá um método provideEventListRepository() que iria retornar uma implementação com dados falsos(somente para testes) e na versão de produção o devido repositório com a implementação para carregar os dados do servidor como será explicado no próximo post na altura de escrever testes para o presenter deste projecto.

Para já, vou sou testar se o ambiente esta devidamente configurado escrevendo um teste unitário simples.

O primeiro passo é criar uma classe dentro do directório tests(como mencionei acima) onde serão escritos todos os testes.

Para escrever uma função de teste, basta simplesmente escrever a função dentro da classe criada e por cima da assinatura do metodo adicionar a anotação @Test para que o JUnitRunner reconheça este método como um teste a executar.
O corpo desta função é composto pela lógica que se pretende testar e um conjunto de métodos disponibilizados na API do JUnit que permitem verificar se o resultado da operação efectuada é igual ao que se está a espera.

Alguns dos métodos para verificar se a lógica esta correcta são:

assertEquals(Object esperado, Object actual): Permite verificar se dois objectos são iguais e o teste falha se os objectos forem diferentes.

assertTrue(boolean expressão): Permite verificar se a expressão passada como parâmetro é verdadeira. Se a expressão for falsa o teste irá falhar.

assertNotNull(Object object): Permite verificar se o objecto passado não é null. Se o objecto for nul o teste irá falhar.

Utilizando estes métodos é possível escrever testes unitários como o teste abaixo que verifica se um método de soma está a funcionar de forma correcta.

public class BasicTest{

public int sum(int a, int b){
return a+b;
}

@Test
public void testSum(){
int a = 5;
int b = 4;
int result = sum(a,b);
assertTrue(result == 9);
}
}

Para executar este teste, basta simplesmente clicar no botão direito por cima do ficheiro, seleccionar a opção “Run..<nome da class> e em poucos segundos o android studio irá apresentar os resultados na tab Run como mostra a imagem abaixo.

E desta forma chegamos ao fim de mais um post em que foi possível fazer a configuração de um ambiente de testes, escrever e executar um teste unitário básico.

Continuaremos no próximo post para escrever testes do presenter e relacionar alguns dos conceitos apresentados neste post a escrita de testes mais complexos.

Caso tenhas gostado do post, deixe ficar um like clicando no coraçãozinho abaixo e partilhe com amigos que achas que também poderão achar interessante.

Caso tenhas alguma dúvida ou sugestão, deixe-a ficar escrevendo um comentário na secção abaixo.

Ate a próxima!

DM =)

--

--

Dario Mungoi
Google Developer Experts

Senior Android Developer at @Shopify, Design Sprint Master, former Android GDE