Introdução ao Espresso

Doílio Abel Matsinhe
GDG Maputo
Published in
5 min readAug 30, 2018
Instrumentation Testing Framework

O que é Espresso? 🤔

Espresso é uma estrutura de teste de instrumentação disponibilizada pelo Google para facilitar o teste da interface do usuário.

Por quê usar?

Acredito que a maioria dos desenvolvedores já fizeram algum tipo de teste nos seus aplicativos, sejam testes básicos num cenário de vida real, simplesmente para verificar se a soma de duas variáveis correspondem a um certo valor, ou se uma Activity está a comportar-se da forma como devia ao usarmos um Intent.

Escrever bons testes pode ser um desafio, e executar um teste confiável para interface de Usuário pode ser substancialmente mais difícil ainda.

Interfaces de Usuário são:

  • Assíncronas
  • Orientadas por eventos, transições e dados carregados por tarefas em segundo plano.

Codificar em torno disso sem qualquer ajuda de uma estrutura de teste de interface do usuário exigiria muito trabalho.

O Framework Espresso foi criado Justamente para este proposito, para permitir que desenvolvedores possam criar Testes de UI que são:
Concisos, Confiáveis e usando uma API fluente.

Suponhamos que eu lhe entregue um telemóvel com um aplicativo, para testar uma funcionalidade que acabo de implementar. como por exemplo verificar se a minha App envia mensagens de uma Activity para a outra de forma correcta.

O que você faria?

  1. Encontrar a View: Que permite inserir a mensagem.
  2. Executar uma acção: Neste caso seria escrever a mensagem.
  3. E por fim, Inspeccionar o Resultado: Verificando se a mensagem que foi escrita corresponde com a mensagem que foi enviada.

Isto é simples de entender para uma pessoa. Mas como codificariamos isto?🤷‍

Simples, basta-nos perceber os principais componentes do Espresso: Espresso, ViewMatchers, ViewActions, e ViewAssertions.

1. Espresso

Ponto de entrada para interacções com views(via onView() e onData()).

2. ViewMatchers

Uma colecção de objectos que implementam a interface Matcher<?superView>. Você pode passar um ou mais destes para o método onView() para localizar uma visão dentro da hierarquia de visão actual.

3. ViewActions

Uma coleção de objetos ViewAction que podem ser passados ​​para o método ViewInteraction.perform(), como por exemplo: click().

4. ViewAssertions

Uma coleção de objetos ViewAssertion que podem ser passados ​​pelo método ViewInteraction.check(). Na maioria das vezes, usaremos o Assertion “matches”, com um ViewMatcher, para confirmar o estado da exibição de uma view.

O fluxo de teste que usamos anteriormente não se difere da anatomia do Espresso:

  1. Primeiro encontramos a view com onView(Matcher<View>)
  2. De seguida executamos uma accao usando .perform(ViewAction)
  3. E por fim verificamos o resultado com .check(ViewAssertion)

Agora vamos a um exemplo prático👨‍💻

Para o exemplo que preparei, criei um aplicativo simples que envia uma mensagem de uma activity para a outra. Vamos implementar alguns métodos para testar o aplicativo com o Espresso. O aplicativo pode ser baixado no seguinte LINK.

Parte 1

Após termos baixado o aplicativo e importado para o nosso Android Studio, ja podemos comecar.

  1. Adicione as seguintes dependencias ao build.gradle da app:
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'

2. Adicione tambem a linha de codigo abaixo e sincronize o programa.

defaultConfig{
testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner”
}

O AndroidJUnitRunner é o ponto de entrada para executar todos os nossos testes. Ele controla o ambiente de teste, o apk e inicia todos os testes definidos no nosso pacote de testes.

Parte 2

Os testes de Instrumentação ficam na pasta (androidTest). Então,

  1. Primeiro vamos criar uma classe onde faremos os nossos testes, podemos chamar de EspressoUITest.
@RunWith(AndroidJUnit4.class)
public class EspressoUITest {

@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<> (MainActivity.class);
}

Até aqui já temos duas Annotations: @RunWith e @Rule.

O @RunWith serve para criar classes de testes de instrumentação com JUnit4.

O @Rule permite-nos alterar o comportamento de cada método de teste de forma reusável. o teste supracitado usa ActivityTestRule(providencia métodos para testar uma unica activity, neste caso a MainActivity).

Parte 3

Agora vamos começar com o teste, vamos criar um método void chamado testarActivities onde iremos testar se as views aparecem, após clicarmos os botões Enviar.

@Test
public void testarActivities(){
onView(withId(R.id.enviar)).perform(click());
onView(withId(R.id.titulo1)).check(matches(isDisplayed()));

onView(withId(R.id.enviar1)).perform(click());
onView(withId(R.id.titulo)).check(matches(isDisplayed()));
}

Não podemos esquecer-nos da Annotation @Test, pois ela é que diz ao JUnit que o método em questão é para testes.

Na primeira linha, fizemos uma combinação de um ViewMatcher (usado para encontrar a view onde vamos efectuar a acção) e um ViewAction (usado para efectuar a acção que neste caso foi o click do botão).

onView(withId(R.id.enviar)).perform(click());

Na segunda linha, fizemos uma combinação de um ViewMatcher (usado para encontrar a view onde vamos efectuar a acção neste caso o titulo da 2ª Activity) e um ViewAssertion(usado para verificar se o titulo descrito no matcher aparece na 2ª Activity).

onView(withId(R.id.titulo1)).check(matches(isDisplayed()));

Nas linhas seguintes efectuamos o mesmo processo para testar se o titulo da Activity1 aparecerá ao efectuarmos o click do botão enviar na Activity2.

onView(withId(R.id.enviar1)).perform(click());
onView(withId(R.id.titulo)).check(matches(isDisplayed()));

Para corrermos o teste simplesmente clicamos com botão direito na Classe EspressoUITest, clicamos em Run ‘EspressoUITest’ e de seguida escolhemos onde fazer o teste, pois este pode ser feito no emulador ou no nosso dispositivo.

Quando o teste começar observe o dispositivo a executar o código. clicando o botão na primeira activity, de seguida clicando o botão da 2ª activity automaticamente.

Não não dona Olivia, Não é Magia. Esse é o poder do Espresso… lol

Se tudo tiver corrido bem veremos um: All Tests passed no canto inferior esquerdo, indicando que os testes foram efectuados com sucesso.

Caso contrário, veremos um circulo vermelho, e erros a espera de serem corrigidos.

Parte 4

Chegamos a 4ª e ultima parte deste artigo, onde iremos testar se as mensagens escritas pelo usuário na 1ª Activity correspondem a mensagem recebida na 2ª Activity, vamos criar um outro método void chamado testeInputOutput, e usaremos a mesma lógica.

@Test
public void testeInputOutput(){
onView(withId(R.id.mensagem)).perform(typeText("I've heard that Rosario is Batman"));
onView(withId(R.id.enviar)).perform(click());
onView(withId(R.id.mensagem_recebida1)).check(matches(withText("I've heard that Rosario is Batman")));
}

Na primeira operação, fizemos uma combinação de um ViewMatcher (usado para encontrar a view onde vamos efectuar a acção) e um ViewAction (usado para efectuar a acção que neste caso foi inserir texto).

onView(withId(R.id.mensagem)).perform(typeText("I've heard that Rosario is Batman"));

Na segunda operação, fizemos uma combinação de um ViewMatcher (usado para encontrar a view onde vamos efectuar a acção) e um ViewAction (usado para efectuar a acção que neste caso foi efectuar um click).

onView(withId(R.id.enviar)).perform(click());

Por fim, fizemos a combinação de um ViewMatcher (usado para encontrar a view onde vamos efectuar a acção) e um ViewAssertion(usado para verificar se o texto inserido na 1a Activity corresponde ao texto recebido na 2ª activity).

onView(withId(R.id.mensagem_recebida1)).check(matches(withText("I've heard that Rosario is Batman")));

Corra somente o métodotesteInputOutput e veja o programa a ser executado automaticamente.

E aqui temos o método a ser executado automaticamente

Nosso Código Completo deve estar assim:

EspressoUITest
Divirtam-se com o Espresso.

E assim concluimos a introdução ao Framework Espresso. Agradeço por terem lido, espero que tenha sido útil. Para Sugestões, criticas, podem encontrar me em Instagram, Twitter , LinkedIn, Github .

--

--

Doílio Abel Matsinhe
GDG Maputo

Associate Android developer| PC Gamer| Tech Lover From Mozambique