Pablo Guardiola
Testeas o k ase??
@Guardiola31337 - pguardiola.com
Agenda
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Importancia del testing sobre dispositivos móviles

‣

Robole...
Numerosas apps en los markets = Competencia brutal
Pablo Guardiola
‣
‣

@Guardiola31337 - pguardiola.com

Número de apps A...
Numerosas apps en los markets = Competencia brutal
Pablo Guardiola
‣
‣

@Guardiola31337 - pguardiola.com

Porcentaje de ap...
¿El código hace exactamente lo que quieres?
Pablo Guardiola
‣

No cabrees a tus usuarios

@Guardiola31337 - pguardiola.com
¿El código hace exactamente lo que quieres?
Pablo Guardiola

@Guardiola31337 - pguardiola.com
¿Podemos reducir el tiempo dedicado a testing usando tests automáticos?
Pablo Guardiola

‣

@Guardiola31337 -pguardiola.co...
¿Podemos reducir el tiempo dedicado a testing usando tests automáticos?
Pablo Guardiola

‣

@Guardiola31337 - pguardiola.c...
Vivimos en un mundo ágil
Pablo Guardiola
‣

@Guardiola31337 -pguardiola.com

¡Cuidado con las actualizaciones!
Testeas o k ase??
Pablo Guardiola

@Guardiola31337 -pguardiola.com
Ventajas de hacer testing
Pablo Guardiola

‣

@Guardiola31337 - pguardiola.com

Incrementa el nivel de confianza que se tie...
Android testing
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Go, go, go!
Android testing
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

JUnit

‣

Los métodos de android.jar devuelven Stub!
Otras opciones
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Android testing framework

‣

Tests deben ejecutarse ...
Otras opciones
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Separar código Java y Android

‣

POJO’s

‣

Tests in...
Otras opciones
Pablo Guardiola
‣

Entonces, ¿qué?

@Guardiola31337 - pguardiola.com
¿Por qué usar Robolectric?
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Es rápido

‣

Interacción con las clases ...
Además, Robolectric te permite...
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Usar JUnit 4

‣

Iteraciones rápid...
¿Cómo funciona?
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Shadows
¿Cómo funciona?
Pablo Guardiola

@Guardiola31337 - pguardiola.com
¿Cómo funciona?
Pablo Guardiola

@Guardiola31337 - pguardiola.com
¿Cómo funciona?
Pablo Guardiola

‣

@Guardiola31337 - pguardiola.com

Robolectric actúa como un proxy
Show me the code!
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Se debe indicar con una anotación qué clase es la
e...
Show me the code!
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

En ocasiones Robolectric está oculto...
@RunWith(Ro...
Shadows
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Métodos para acceder al estado de los objetos Android
<ImageV...
HTTP testing
Pablo Guardiola

@Guardiola31337 - pguardiola.com

@RunWith(RobolectricTestRunner.class)
public class HttpTes...
HTTP testing
Pablo Guardiola

@Guardiola31337 - pguardiola.com

Robolectric.addPendingHttpResponse(200, "OK");
‣

‣

Robol...
HTTP testing
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Otros ejemplos
@Test public void shouldReturnCorrectResp...
Extendiendo Robolectric
Pablo Guardiola

‣
‣

@Guardiola31337 - pguardiola.com

Robolectric no tiene funcionalidad para to...
Inconvenientes
Pablo Guardiola
‣
‣
‣

@Guardiola31337 - pguardiola.com

No hay clases Shadow para todo
No todo se comporta...
¿Por qué no usar directamente el código Android?
Pablo Guardiola

‣
‣
‣

@Guardiola31337 - pguardiola.com

Difícil consegu...
Robolectric 2.0
Pablo Guardiola

2.0

@Guardiola31337 - pguardiola.com
Robolectric 2.0
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Uso del SDK de Android

‣

No más excepciones Stub!
...
Robolectric 2.0
Pablo Guardiola

‣

‣

‣

@Guardiola31337 - pguardiola.com

El paquete de soporte no usa clases Shadow
Fra...
Robolectric 2.0
Pablo Guardiola

@Guardiola31337 - pguardiola.com

‣

Se pueden testear estilos y temas

‣

Acceso a los r...
Robolectric 2.0
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Testing bajo diferentes configuraciones del dispositiv...
Robolectric 2.0
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

ActivityController mayor control sobre el ciclo de vi...
Robolectric 2.0
Pablo Guardiola

‣

‣

‣
‣
‣

@Guardiola31337 - pguardiola.com

El uso del SDK de Android está aumentando
...
Demo
Pablo Guardiola

@Guardiola31337 - pguardiola.com

Project name: SampleRobolectric
Package name: com.pguardiola.sampl...
Demo
Pablo Guardiola

<groupId>com.pguardiola.samplerobolectric</groupId>
<artifactId>SampleRobolectric</artifactId>
<vers...
Demo
Pablo Guardiola

@Guardiola31337 - pguardiola.com

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactI...
Demo
Pablo Guardiola
‣

@Guardiola31337 - pguardiola.com

Alt+Enter -> Create Test -> JUnit4
@RunWith(RobolectricTestRunne...
Demo
Pablo Guardiola

@Guardiola31337 - pguardiola.com

Imports

‣

import
import
import
import

org.junit.Test;
org.junit...
Demo
Pablo Guardiola

Run -> MyActivityTest
MyActivityTest fails
SampleRobolectric pass

@Guardiola31337 - pguardiola.com
¿Preguntas?
Pablo Guardiola

@Guardiola31337 - pguardiola.com
Gracias
Pablo Guardiola

@Guardiola31337 - pguardiola.com

Happy testing!!
Pablo Guardiola
@Guardiola31337
Upcoming SlideShare
Loading in...5
×

Testeas o k ase??

731

Published on

Slides usadas en la charla Testeas o k ase?? del Codemotion Spain 2013.

En la sesión se pretende explicar la importancia del testing en dispositivos móviles, así como animar a los desarrolladores a que implementen tests unitarios en sus aplicaciones, concretamente usando el framework Robolectric para Android. Se explicará el funcionamiento de la herramienta, mostrando por qué es tan potente junto con las posibilidades que nos ofrece y, finalmente, se enseñará un ejemplo práctico detallando lo fácil que es tanto configurarlo como empezar a escribir tests.

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
731
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
13
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Testeas o k ase??

  1. 1. Pablo Guardiola Testeas o k ase?? @Guardiola31337 - pguardiola.com
  2. 2. Agenda Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Importancia del testing sobre dispositivos móviles ‣ Robolectric ‣ Demo
  3. 3. Numerosas apps en los markets = Competencia brutal Pablo Guardiola ‣ ‣ @Guardiola31337 - pguardiola.com Número de apps Android en el market: 866033 Porcentaje de apps de baja calidad: 23 %
  4. 4. Numerosas apps en los markets = Competencia brutal Pablo Guardiola ‣ ‣ @Guardiola31337 - pguardiola.com Porcentaje de apps con menos de 3 ratings: 43.9 % Porcentaje de apps entre 0 y 4 estrellas: 65.22 %
  5. 5. ¿El código hace exactamente lo que quieres? Pablo Guardiola ‣ No cabrees a tus usuarios @Guardiola31337 - pguardiola.com
  6. 6. ¿El código hace exactamente lo que quieres? Pablo Guardiola @Guardiola31337 - pguardiola.com
  7. 7. ¿Podemos reducir el tiempo dedicado a testing usando tests automáticos? Pablo Guardiola ‣ @Guardiola31337 -pguardiola.com Testing manual = mucho tiempo
  8. 8. ¿Podemos reducir el tiempo dedicado a testing usando tests automáticos? Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Testing automático
  9. 9. Vivimos en un mundo ágil Pablo Guardiola ‣ @Guardiola31337 -pguardiola.com ¡Cuidado con las actualizaciones!
  10. 10. Testeas o k ase?? Pablo Guardiola @Guardiola31337 -pguardiola.com
  11. 11. Ventajas de hacer testing Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Incrementa el nivel de confianza que se tiene del código ‣ Hacer testing “obliga” a escribir código modular ‣ Se desarrolla un producto de calidad
  12. 12. Android testing Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Go, go, go!
  13. 13. Android testing Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ JUnit ‣ Los métodos de android.jar devuelven Stub!
  14. 14. Otras opciones Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Android testing framework ‣ Tests deben ejecutarse en un terminal o emulador
  15. 15. Otras opciones Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Separar código Java y Android ‣ POJO’s ‣ Tests instrumentales ‣ Mocking framework ‣ ¡¡¡NO HACER!!!
  16. 16. Otras opciones Pablo Guardiola ‣ Entonces, ¿qué? @Guardiola31337 - pguardiola.com
  17. 17. ¿Por qué usar Robolectric? Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Es rápido ‣ Interacción con las clases de Android ‣ Incluye HTTP/API testing ‣ Permite invocar métodos privados ‣ Muy fácil de integrar con otros frameworks
  18. 18. Además, Robolectric te permite... Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Usar JUnit 4 ‣ Iteraciones rápidas ‣ Permite aplicar TDD en el desarrollo ‣ Verificar la lógica y el comportamiento frente a la implementación
  19. 19. ¿Cómo funciona? Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Shadows
  20. 20. ¿Cómo funciona? Pablo Guardiola @Guardiola31337 - pguardiola.com
  21. 21. ¿Cómo funciona? Pablo Guardiola @Guardiola31337 - pguardiola.com
  22. 22. ¿Cómo funciona? Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Robolectric actúa como un proxy
  23. 23. Show me the code! Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Se debe indicar con una anotación qué clase es la encargada de realizar el test @RunWith(RobolectricTestRunner.class) // <== REQUIRED for Robolectric! public class HomeActivityTest { @Test public void shouldHaveAButtonThatSaysPressMe() throws Exception { // test code here } }
  24. 24. Show me the code! Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com En ocasiones Robolectric está oculto... @RunWith(RobolectricTestRunner.class) public class HomeActivityTest { @Test public void shouldHaveHappySmiles() throws Exception { String appName = new MyActivity() .getResources().getString(R.string.app_name); assertThat(appName, equalTo("SampleRobolectric")); } } ‣ ¡Escondido! Pero haciendo su trabajo o/
  25. 25. Shadows Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Métodos para acceder al estado de los objetos Android <ImageView android:id="@+id/pivotal_logo" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/pivotallabs_logo" android:layout_marginBottom="10dip" > @Test public void shouldHaveALogo() throws Exception { ImageView pivotalLogo = (ImageView)activity.findViewById(R.id.pivotal_logo); ShadowImageView shadowPivotalLogo = Robolectric.shadowOf(pivotalLogo); assertThat(shadowPivotalLogo.resourceId, equalTo(R.drawable.pivotallabs_logo)); } ‣ Acceso a estado y variables, de otro modo sería imposible
  26. 26. HTTP testing Pablo Guardiola @Guardiola31337 - pguardiola.com @RunWith(RobolectricTestRunner.class) public class HttpTest { @Test public void testGet_FormsCorrectRequest_noBasicAuth() throws Exception { Robolectric.addPendingHttpResponse(200, "OK"); new Http().get("www.codemotion.es",             Maps.<String, String>newHashMap(),             null,             null); assertThat(((HttpUriRequest) Robolectric.getSentHttpRequest(0)).getURI(),             equalTo(URI.create("www.codemotion.es"))); } }
  27. 27. HTTP testing Pablo Guardiola @Guardiola31337 - pguardiola.com Robolectric.addPendingHttpResponse(200, "OK"); ‣ ‣ Robolectric hace de mock server, necesita saber cómo responder a la llamada para evitar RuntimeException Respuesta por defecto compartida @RunWith(RobolectricTestRunner.class) public class HttpTest { @Before public void setup() { Robolectric.addPendingHttpResponse(200, "OK"); } ... }
  28. 28. HTTP testing Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Otros ejemplos @Test public void shouldReturnCorrectResponse() throws Exception { Robolectric .addPendingHttpResponse(666, "it's all cool"); Http.Response response = http.get("www.example.com", new HashMap<String, String>(), null, null);     assertThat(fromStream(response.getResponseBody()), equalTo("it's all cool"));     assertThat(response.getStatusCode(), equalTo(666)); } } ‣ Métodos correctos, cabeceras...
  29. 29. Extendiendo Robolectric Pablo Guardiola ‣ ‣ @Guardiola31337 - pguardiola.com Robolectric no tiene funcionalidad para todo Robolectric permite extender las clases Shadow @Implements @Implementation Robolectric.getDefaultShadowClasses() __constructo__ @RealObject
  30. 30. Inconvenientes Pablo Guardiola ‣ ‣ ‣ @Guardiola31337 - pguardiola.com No hay clases Shadow para todo No todo se comporta del mismo modo que en la DVM Android no es Java
  31. 31. ¿Por qué no usar directamente el código Android? Pablo Guardiola ‣ ‣ ‣ @Guardiola31337 - pguardiola.com Difícil conseguir los .jar reales Difícil trabajar con código nativo Difícil dejar de usar las clases Shadow
  32. 32. Robolectric 2.0 Pablo Guardiola 2.0 @Guardiola31337 - pguardiola.com
  33. 33. Robolectric 2.0 Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Uso del SDK de Android ‣ No más excepciones Stub! ‣ Objetivo eliminar el 99% de las clases Shadow
  34. 34. Robolectric 2.0 Pablo Guardiola ‣ ‣ ‣ @Guardiola31337 - pguardiola.com El paquete de soporte no usa clases Shadow Fragments, action bar, loaders usan su implementación real Tests tendrán mismo comportamiento que en los dispositivos
  35. 35. Robolectric 2.0 Pablo Guardiola @Guardiola31337 - pguardiola.com ‣ Se pueden testear estilos y temas ‣ Acceso a los recursos del sistema ‣ Soporte ActionBarSherlock ‣ Mejoras de rendimiento y corrección de bugs
  36. 36. Robolectric 2.0 Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Testing bajo diferentes configuraciones del dispositivo @Test @Config("en") public void shouldGiveEnglishResponses() throws Exception { assertThat(activity.findViewById(R.id.message)) .hasText("Hello!"); } } @Test @Config("fr") public void shouldGiveFrenchResponses throws Exception { assertThat(activity.findViewById(R.id.message)) .hasText("Bonjour!"); } }
  37. 37. Robolectric 2.0 Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com ActivityController mayor control sobre el ciclo de vida FooActivity foo = Robolectric.buildActivity(FooActivity.class)         .create().start().resume().get(); ActivityController<FooActivity> fooController = Robolectric.buildActivity(FooActivity.class).create(); FooActivity foo = fooController.get(); // Ensure the user was injected. assertThat(foo.user).isNotNull(); // Log the user out. foo.user.expireSession(); fooController.start().resume(); // Ensure the activity is now finishing. assertThat(foo).isFinishing();
  38. 38. Robolectric 2.0 Pablo Guardiola ‣ ‣ ‣ ‣ ‣ @Guardiola31337 - pguardiola.com El uso del SDK de Android está aumentando considerablemente Todo el mundo puede contribuir: https://github.com/robolectric/robolectric http://robolectric.org/ http://robolectric.blogspot.com.es/
  39. 39. Demo Pablo Guardiola @Guardiola31337 - pguardiola.com Project name: SampleRobolectric Package name: com.pguardiola.samplerobolectric Activity name: MyActivity Add Framework Support -> Maven
  40. 40. Demo Pablo Guardiola <groupId>com.pguardiola.samplerobolectric</groupId> <artifactId>SampleRobolectric</artifactId> <version>1.0-SNAPSHOT</version> <packaging>apk</packaging> <name>My Sample App</name> <dependencies> <dependency> <groupId>com.google.android</groupId> <artifactId>android</artifactId> <version>4.1.1.4</version> <scope>provided</scope> </dependency> <!-- Make sure this is below the android dependencies --> <dependency> <groupId>org.robolectric</groupId> <artifactId>robolectric</artifactId> <version>2.1.1</version> <scope>test</scope> </dependency> @Guardiola31337 - pguardiola.com
  41. 41. Demo Pablo Guardiola @Guardiola31337 - pguardiola.com <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>android-maven-plugin</artifactId> <version>3.6.1</version> <configuration> <sdk> <!-- platform or api level (api level 16 = platform 4.1)--> <platform>18</platform> </sdk> <undeployBeforeDeploy>true</undeployBeforeDeploy> </configuration> <extensions>true</extensions> </plugin> </plugins> </build>
  42. 42. Demo Pablo Guardiola ‣ @Guardiola31337 - pguardiola.com Alt+Enter -> Create Test -> JUnit4 @RunWith(RobolectricTestRunner.class) public class MyActivityTest { @Test public void shouldHaveHappySmiles() throws Exception { String appName = new MyActivity().getResources() .getString(R.string.app_name); assertThat(appName, equalTo("SampleRobolectric")); } }
  43. 43. Demo Pablo Guardiola @Guardiola31337 - pguardiola.com Imports ‣ import import import import org.junit.Test; org.junit.runner.RunWith; org.robolectric.RobolectricTestRunner; static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat;
  44. 44. Demo Pablo Guardiola Run -> MyActivityTest MyActivityTest fails SampleRobolectric pass @Guardiola31337 - pguardiola.com
  45. 45. ¿Preguntas? Pablo Guardiola @Guardiola31337 - pguardiola.com
  46. 46. Gracias Pablo Guardiola @Guardiola31337 - pguardiola.com Happy testing!! Pablo Guardiola @Guardiola31337
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×