Concrete Logo
Hamburger button

Como fazer Integração Contínua no Android – parte 4

  • Blog
  • 9 de Abril de 2014
Share

Seguindo nossa saga rumo a builds automatizados completos fora da IDE, chegamos aos famigerados testes. Para você que chegou agora, aqui está a parte 1, aqui a parte 2 e aqui a parte 3 desta série.

Muitos devem se perguntar: testes em mobile? Por incrível que pareça, e já anteriormente relatado aqui no blog, muita gente nem sabe como ou o que testar em aplicações mobile. A desculpa em geral é:

Não automatizamos porque não temos tempo porque não automatizamos.

Aqui vamos demonstrar a estrutura do projeto de teste para o demonstrado no passo 3.

Vamos usar o eclipse para gerar um projeto teste normal. Para isso, digite CTRL + N (ou vá em File -> New -> Other) e selecione Android Test Project:

Android Test Project Creation

Em geral o nome do projeto de teste é o mesmo que o projeto que será testado com o sufixo “Test” (é bom seguir as guidelines do Google).

Não temos o intuito aqui de explicar muito sobre como testar aplicações Android. Porém seremos bonzinhos e deixaremos alguns links no final para alguns frameworks de test que podem ajudar bastante.

Ao terminar de criar o projeto, falta “mavenizarmos” ou, melhor falando, adicionar suporte para o projeto ser compilado e rodado com o Maven. Como já vimos anteriormente (vide parte 3) o básico do Maven, vamos criar um pom.xml MUUUUUUUITO parecido com o do projeto anterior. Precisamos dizer nesse projeto quais serão os dados de identificação (groupId, artefactId, version, etc), qual serão nossas dependências (de novo o android e o android-test), definir o nosso build e acrescentar a configuração de repositórios locais. Vamos por partes!

A identificação do projeto ficará simples:

[code language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0
https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>br.com.concretesolutions</groupId>
<artifactId>exemplo-ic-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>apk</packaging>
[/code]

Depois teremos as propriedades básicas que definem o encoding dos arquivos, o nível da plataforma e as versões do android e do plugin de compilação android-maven-plugin:

[code language=”xml”]
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<api.platform>18</api.platform>

<android.version>4.1.1.4</android.version>
<android-maven-plugin.version>3.8.1</android-maven-plugin.version>
</properties>
[/code]

Agora temos que definir as dependências. Para o projeto teste precisamos tanto do Android e do Android-test. Fora isso, como o código que queremos testar está em outro projeto, teremos que incluir o próprio projeto como dependência. Faremos isso incluindo dois tipos de dependência: nosso projeto em formato apk e nosso projeto em formato jar. O jar é para nossas classes de teste poderem encontrar o as classes do projeto. Já o apk é para o projeto de teste saber qual projeto ele está testando no device ou emulador.

Assim temos:

[code language=”xml”]
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>${android.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android-test</artifactId>
<version>${android.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>br.com.concretesolutions</groupId>
<artifactId>exemplo-ic</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
<type>apk</type>
</dependency>
<dependency>
<groupId>br.com.concretesolutions</groupId>
<artifactId>exemplo-ic</artifactId>
<type>jar</type>
<scope>provided</scope>
<version>${project.version}</version>
</dependency>
</dependencies>
[/code]

Reparem que o escopo das dependências é “provided”. Isso porque o projeto precisa estar instalado no dispositivo ANTES de podermos executar os testes. Provided indica aqui que estas dependências JÁ ESTARÃO DISPONÍVEIS no device ou emulador.

Depois temos nosso build idêntico ao anterior:

[code language=”xml”]
<build>
<sourceDirectory>src</sourceDirectory>
<outputDirectory>bin/classes</outputDirectory>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>${android-maven-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<extractDuplicates>true</extractDuplicates>
<sdk>
<platform>${api.platform}</platform>
</sdk>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<versionRange>${android-maven-plugin.version}</versionRange>
<goals>
<goal>consume-aar</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
[/code]

Aqui temos o plugin que possibilita o projeto ser do tipo apk (é importante marcar o plugin como true caso contrário o Eclipse não entenderá o packaging como apk) e um pluginManagement para ignorar a fase consume-aar.

Por último, precisamos incluir os mesmos repositórios que estão no projeto a ser testado. Caso contrário o Maven irá se perder na hora do build. Como configuramos um repositório dentro do projeto (lembram do private_libs???), precisamos criar só a raiz desse repositório também (só criar um diretório vazio na raiz do projeto de tests com o mesmo nome que utilizamos anteriormente, ou seja, “private_libs”). Com isso temos:

[code language=”xml”]
<repositories>
<repository>
<id>android-repo</id>
<url>file://${ANDROID_HOME}/extras/android/m2repository</url>
</repository>
<repository>
<id>android-libs</id>
<url>file://${project.basedir}/private_libs</url>
</repository>
</repositories>

<!– Fim do pom –>
</project>
[/code]

That’s all folks! Projeto configurado! Vamos criar um teste só para garantir que está tudo bem.

Seu projeto de teste deve estar parecido com o seguinte:

Android Test Project

Reparem que criei uma classe de teste chamada MainActivityTest. Lembram das guidelines do Google? Pois bem… siga com cuidado nessa parte de teste. Nomenclatura de tests e preparação das classes de teste são importantes nesse caso.

Na classe MainActivityTest não tem segredo. Não farei um teste muito válido, mas é só para mostrar rodando com o Maven. Olha só que belezura de teste:

[code language=”java”]
package br.com.concretesolutions.exemplo.ic;

import android.test.ActivityInstrumentationTestCase2;

public class MainActivityTest extends
ActivityInstrumentationTestCase2<MainActivity> {

private MainActivity mainActivity;

public MainActivityTest() {
super(MainActivity.class);
}

@Override
protected void setUp() throws Exception {
mainActivity = getActivity();
}

public void testHelloWorld() {
assertNotNull(mainActivity);
}
}
[/code]

Estamos testando que a Activity não estará nula no nosso teste. Ou seja, só preparamos para você brincar com a Activity no teste. O resto é com você!

Para executar esse projeto é mais fácil do que o outro. Basta executar:

[code language=”shell”]
mvn clean install -U
[/code]

Lembrando que o “-U” irá forçar a atualização das dependências.

O resultado deverá ter algo no fim parecido com:

[code language=”shell”]
[INFO] — android-maven-plugin:3.8.1:internal-pre-integration-test (default-internal-pre-integration-test) @ exemplo-ic-test —
[INFO] Waiting for initial device list from the Android Debug Bridge
[INFO] Found 1 devices connected with the Android Debug Bridge
[INFO] android.device parameter not set, using all attached devices
[INFO] Device 4df180a802635f37_samsung_GT-I9300 found.
[INFO] 4df180a802635f37_samsung_GT-I9300 : Successfully installed /home/victor/.m2/repository/br/com/concretesolutions/exemplo-ic/0.0.1-SNAPSHOT/exemplo-ic-0.0.1-SNAPSHOT.apk to 4df180a802635f37_samsung_GT-I9300
[INFO] Found 1 devices connected with the Android Debug Bridge
[INFO] android.device parameter not set, using all attached devices
[INFO] Device 4df180a802635f37_samsung_GT-I9300 found.
[INFO] 4df180a802635f37_samsung_GT-I9300 : Successfully installed /home/victor/dev/android/workspace/exemplo-android-ic-test/target/exemplo-ic-test-0.0.1-SNAPSHOT.apk to 4df180a802635f37_samsung_GT-I9300
[INFO]
[INFO] — android-maven-plugin:3.8.1:internal-integration-test (default-internal-integration-test) @ exemplo-ic-test —
[INFO] Found 1 devices connected with the Android Debug Bridge
[INFO] android.device parameter not set, using all attached devices
[INFO] Device 4df180a802635f37_samsung_GT-I9300 found.
[INFO] 4df180a802635f37_samsung_GT-I9300 : Running instrumentation tests in br.com.concretesolutions.exemplo.ic.test
[INFO] 4df180a802635f37_samsung_GT-I9300 : Run started: br.com.concretesolutions.exemplo.ic.test, 0 tests:
[INFO] 4df180a802635f37_samsung_GT-I9300 : Run ended: 0 ms
[INFO] Tests run: 0, Failures: 0, Errors: 0
[INFO] 4df180a802635f37_samsung_GT-I9300 : Report file written to /home/victor/dev/android/workspace/exemplo-android-ic-test/target/surefire-reports/TEST-4df180a802635f37_samsung_GT-I9300.xml
[INFO]
[INFO] — maven-install-plugin:2.5.1:install (default-install) @ exemplo-ic-test —
[INFO] Installing /home/victor/dev/android/workspace/exemplo-android-ic-test/target/exemplo-ic-test-0.0.1-SNAPSHOT.apk to /home/victor/.m2/repository/br/com/concretesolutions/exemplo-ic-test/0.0.1-SNAPSHOT/exemplo-ic-test-0.0.1-SNAPSHOT.apk
[INFO] Installing /home/victor/dev/android/workspace/exemplo-android-ic-test/pom.xml to /home/victor/.m2/repository/br/com/concretesolutions/exemplo-ic-test/0.0.1-SNAPSHOT/exemplo-ic-test-0.0.1-SNAPSHOT.pom
[INFO] Installing /home/victor/dev/android/workspace/exemplo-android-ic-test/target/exemplo-ic-test-0.0.1-SNAPSHOT.jar to /home/victor/.m2/repository/br/com/concretesolutions/exemplo-ic-test/0.0.1-SNAPSHOT/exemplo-ic-test-0.0.1-SNAPSHOT.jar
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 28.859s
[INFO] Finished at: Wed Apr 09 16:48:13 BRT 2014
[INFO] Final Memory: 23M/349M
[INFO] ————————————————————————
[/code]

Chuck Norris estará feliz na nossa Integração Contínua!

Assim já estamos com tudo na mão para irmos para o Jenkins. Podemos melhorar incluindo alguns plugins de reporting, cobertura de testes e etc. Falaremos sobre a cobertura especificamente na próxima parte da série e por ÚLTIMO vamos ao Jenkins.

Ficam aqui alguns links para testar no Android:

Boa integração para todos! E se você tiver alguma dúvida, é só falar aqui embaixo nos comentários.