# Android/Android test
## Introducció a Android Test dins de Android Studio

Android Test és un conjunt d'eines destinades a facilitar el testeig d'una aplicació dins dels nostres projectes Android mitjançant APIs de testeig.

### Introducció a les APIs de testeig

Una pràctica habitual a l'hora de realitzar la comprovació de les funcions és usar avisadors que en temps d'execució ens permetin monitorar la nostra aplicació. Això no obstant, la forma més adient de testejar l'aplicació és mitjançant eines especialitzades per testeig.
JUnit és el framework de testeig principal, inclòs al propi framework d'Android, que s'empra per realitzar operacions de configuració, posada a prova i asserció. D'altra banda, existeixen altres APIs de testeig que complementen a JUnit per tal de proporcionsr al programador més facilitats i funcionalitats.
Dins el projecte d'Android Studio, els fitxers de codi per a testeig han d'anar al directori nom-modul/src/androidTest/java/. Normalment l'IDE ja crea aquest directori al crear el projecte. Abans de començar, cal assegurar-se de que tenim instalada la Llibreria de Suport de Testeig d'Android, la qual proveeix d'APIs per construir i executar codi de testeig a la app. La llibreria inclou un executador de tests de JUnit 4 (AndroidJUnitRunner) i APIs per fer tests funcionals de la interfície d'usuari (Espresso i UI Automator).

### Local Unit Test

Local Unit Test té com a objectiu provar el correcte funcionament de les classes i/o interfícies de les nostres aplicacions. Se'n diu "Local", ja que el test s'executa en la maquina emprada per desenvolupar (prescindeix d'un dispositiu extern on efectuar el testeig), i "Unit" perquè pretén provar la funcionalitat de la unitat més petita possible de codi (un mètode, classe o component). Els tests unitaris son una pràctica habitual (i aconsellable) en els entorns de programació en Java i, per tant, no son una peculiaritat pròpia d'Android.
Donada una classe Java qualsevol del nostre projecte d'Android i les seves possibles operacions, l'Android Studio ens proporciona una manera automatitzada de crear una classe Test per a aquesta classe. La classe resultant contindrà una funció de Test per a cada operació de la classe original i la instrumentació necessària per a comprovar que aquestes retornen els valors esperats. Més endavant es mostra un exemple per a veure-ho amb més detall.
Per tal de tenir accès als components que es mostrarien a una Activity, s'empra una biblioteca que simula la del framework real (android.jar). La raó d'utilitzar aquestes dependències, anomenades Mock Android dependencies, és la de testejar més fàcilment els components amb els que es poden interactuar i evitar dependre de qualsevol comportament particular de la plataforma d'Android. Qualsevol crida directa a un mètode de les classes d'Android (això és, sense passar per les dependències mock) causarà una excepció.

### Instrumentation Test

Donada una Activity qualsevol, l'Android Studio també ens proporciona la possibilitat d'escriure una sèrie d'interaccions a simular, tal com entrar text a un camp de text (EditText) o premer un botó (Button). I, igual que el Unit Test, també en podem extreure informació continguda a la Activity per comprovar que els resultats son els esperats. A diferència del Local Unit Test, com que efectua interaccions sobre components reals que es mostren a una Activity, requereix de dispositius físics o emulats per tal d'executar el(s) test(s).
Un cop ja tinguem la biblioteca de suport de testeig, cal afegir les dependències al fitxer build.gradle.

## Annotacions de JUnit

Dins d'una classe de testeig que integra JUnit 4, podem indicar, mitjançant anotacions en el codi, una execució característica pels diferents mètodes. Cada anotació s'inclou a la línia de codi que precedeix la capçalera del mètode que es vol tractar, i va seguida del símbol '@'. Les possibles anotacions que JUnit 4 suporta són les següents:

### @Before

Especifica que el bloc de codi que el succeeix conté operacions a fer previament a un mètode de testeig. La classe de testeig crida aquest bloc abans de cada mètode de testeig. És possible tenir l'anotació @Before en múltiples mètodes, malgrat que l'ordre en què la classe de testeig crida cadascun d'aquests mètodes serà indefinit. Un possible ús de l'anotació Before és el de realitzar una sèrie d'operacions de preparació o configuració prèvia a un o diversos mètodes.

### @After

Especifica que el bloc de codi que el succeeix conté operacions a fer posteriorment a un mètode de testeig. La classe de testeig crida aquest bloc després de cada mètode de testeig. És possible tenir l'anotació @After en múltiples mètodes, malgrat que l'ordre en què la classe de testeig crida cadascun d'aquests mètodes serà indefinit. Un possible ús de l'anotació After és el de desfer els canvis que un o diversos mètodes han realitzat.

### @Test

Indica que un bloc de codi és un mètode de testeig. Una única classe de testeig pot contenir múltiples mètodes de testeig, precedides d'aquesta anotació.

### @Rule

Una regla permet flexiblement afegir o redefinir el comportament de cada mètode de testeig de forma reusable. Aquesta s'ha de cridar abans de definir un atribut pertinent a una de les classes de regles de testeig que les biblioteques de suport de testeig (Android Testing Support Library) proporcionen, com per exemple, ActivityTestRule o ServiceTestRule.

### @BeforeClass

Especifica mètodes estàtics per cada classe de testeig que només s'han d'invocar un cop. Aquest pas dins del testeig és útil per operacions costoses com per exemple, una connexió a una base de dades.

### @AfterClass

Especifica mètodes estàtics per a què la classe de testeig els invoqui un sol cop després que s'hagin efectuat tots els tests de la classe. Aquest pas és útil per alliberar qualsevol recurs assignat als blocs amb anotació @BeforeClass.

### @Test(timeout=)

Algunes anotacions suporten la possibilitat de passar elements als quals se'ls poden establir valors. Per exemple, es pot especificar un període de timeout per a un test. Si el testeig s'inicia però no es completa dins del període indicat pel timeout, automàticament falla. És necessari especificar el període de timeout en mil·lisegons, per exemple: @Test(timeout=5000).
A part del paràmetre timeout, l'anotació @Test també suporta com a paràmetre una classe que hereti de la classe Throwable. Per tal d'indicar que el test s'ha completat amb èxit, el mètode ha de causar una excepció sense capturar de la classe especificada. Del contrari es considerarà fallit.

## Unit Test en acció

A continuació mostrem com funciona l'Unit Test amb un programa de prova anomenat BasicSample. Aquest programa consisteix en dues Activity.
La primera Activity està formada per un component EditText, sobre el qual l'usuari introdueix un text i un TextView per on es mostrarà el text introduït. Per tal de mostrar el text, es fa ús d'un tercer component Button que mostrarà en el TextView el text introduït en l'EditText. També hi ha un segon Button que crea la segona Activity.
La segona Activity simplement conté un TextView amb el mateix valor que el TextView de la primera Activity.
| Pantalla inicial - Activity 1 | Escenari de prova - Activity 1 | Escenari de prova - Activity 2 |

### Afegir dependències

Per poder fer el testeig és necessari afegir al build.gradle (Module: app) una sèrie de dependències:

### Creació de la classe de testeig

Per a crear la classe de testeig hem de fer clic dret sobre el nom de la classe de la qual volem crear el test, ens situem sobre el nom de la classe, fem boto dret, anem fins a Go To i seleccionem Test.
Ens apareixerà un menú com el de la imatge que es mostra a continuació, en la qual podem configurar les classes i mètodes de les quals volem fer el test. També podem auto generar el @Before i @After.
Una vegada fet això se ens crearà la classe de testeig per a la nostra classe buida. A partir d’aquí podem implantar els mètodes per a provar la nostra classe.

### Clase de testeig

Un cop implementades les Activity y/o les classes, es recomanable crear una classe de testeig per comprovar que tot funcionen tal y com hem indicat. En el nostre exemple, la classe de testeig ha sigut emprada de la següent manera:
Com a atributs tenim una variable STRING_TO_BE_TYPED de tipus String que conté la paraula "Espresso" el qual introduirem més endavant al EditText i un objecte del tipus ActivityTestRule. Aquest segon objecte defineix sobre quina Activity opera la classe de testeig, que en aquest cas, és la MainActivity. A l'inicialitzar aquest objecte, es crea i mostra la Activity, i exposa la Activity sota prova. Aquest seguit d'accions que s'han desencadenat al inicialitzar l'objecte, substitueixen la rutina del desenvolupador a l'hora de testejar manualment els canvis realitzats al codi font.
El mètode changeText_sameActivity introdueix el text que conté l'atribut STRING_TO_BE_TYPED sobre l'EditText i fa clic sobre el botó changeTextBt. Finalment, comprova que el valor del TextView coincideix amb l'String introduït.
El segon i últim mètode, changeText_newActivity, fa clic sobre el Button activityChangeTextBtn, el qual n'és responsable de crear la segona Activity, i comprova que el TextView situat a aquesta Activity coincideix amb l'atribut STRING_TO_BE_TYPED.

### Execució del test

El darrer pas del testeig consisteix a executar el codi de les classes creades, que en aquest exemple és la classe ChangeTextBehaviorTest. Ens dirigim a l'arbre de fitxers del projecte, fem clic dret sobre el document ChangeTextBehaviorTest i "Run ChangeTextBehaviorTest".
En cas que ens aparegui una finestra demanant un dispositiu on executar l'aplicació, escollim una màquina que incorpori la mateixa API que la del nostre projecte i premem OK.
El dispositiu seleccionat executarà l'aplicació i efectuarà les interaccions i comprovacions programades a la classe de testeig. Tot seguit es tancarà l'aplicació. Si hem seguit bé els passos, la consola ens mostrarà cada operació de tipus @test amb resultat success.
A la barra lateral de la consola tenim un llistat de les comprovacions realitzades i el seu resultat:

### Opcions d’execució i depuració

Es pot modificar la configuració com s’executa un paquet, quins mòduls es caregen, el paquet que se implementa, el dispositiu de destí, opcions de logcat i altres.
Per a editar la configuració de execució y depuració, hem de anar a Run > Edit Configurations.
Seleccionem Edit Configurations de la llista desplegable Select Run/Debug Configuration.
Aquest es el panel per defecte per modificar les opcions d’execució, en aquest panell trobem diverses opcions modificables. Podem crear perfils d’execució propis segons les nostres necessitats.

## Altres eines per testejar
### Robotium

Robotium és un framework per a l'automatització del testeig amb JUnit i altres eines de testeig suportades a Android. A continuació es llisten una sèrie de les característiques principals que ens aporta Robotium:
* Funciona tant amb Android Studio com Eclipse.
* Proporciona suport complet per a aplicacions tant natives com híbrides d'Android.
* Suport tant pel codi font com per a binaris APKs.
* Detecció automàtica de ID's de recursos.

### UIAutomator

És un framework elaborat per Google que es caracteritza per les següents característiques:
* Permet realitzar operacions, com obrir el menú d'opcions o el launcher de l'app, en un dispositiu de prova.
* Descobreix fins a un 80% dels defectes, en funció de la plataforma Android.
* Permet realitzar scripts o eines que siguin executades sobre diferents plataformes Android per a reproduir situacions complexes.
* Es pot integrar amb el framework de testeig TestNG per tal de generar informes detallats.

### Espresso

És una API elaborada per Google amb la intenció d'automatitzar el testeig en el cicle de vida del desenvolupament. Compta amb les següents característiques:
* Testeja interaccions, expectacions d'estat i assercions.
* Evita la distracció de codi repetitiu, creació d'una infraestructura o complicacions en detalls de la implementació.
* Sincronització amb el thread de la UI sense necessitat de forçar-lo a entrar en estat sleep.
* Permet testejar el comportament de components WebView dins l'Activity mitjançant l'API WebDrivers.

### Appium

És una eina open source d'automatització de testeig amb l'objectiu que sigui possible reusar el codi entre iOS i Android a més a més de prescindir d'un SDK.
* Permet testejar els tres tipus d'aplicació mòbil: nativa, web mòbil i híbrida.
* No requereix modificar l'aplicació ni recompilar-la.
* Permet escollir el llenguatge en el que es vol escriure el test.
* Es comporta com un servidor web, amb un client i un servidor, mitjançant una REST API.

### Calabash

És una eina open source gratuïta que permet el testeig d'aplicacions entre diverses plataformes. Algunes de les seves característiques principals són:
* Funciona amb totes les APIs actuals tant d'Android com de iOS i per tant també permet testejar aplicacions híbrides.
* Permet provar tant pulsacions com gestos i rotacions.
* Assertions, identifica automàticament elements del codi.
* Permet el testeig d'aplicacions sobre més de 1000 dispositius al núvol.

### UI/Application Exerciser Monkey

Es una eina que fent servir l’emulador d’Android o un dispositiu connectat per ADB permet emular un comportament aleatori per tal de provar la nostra aplicació.
* Funciona per a qualsevol API d’Android.
* Genera pulsacions i rotacions de manera aleatòria
* Configuració bàsica i senzilla.
* Opcions de Debugging

### Comparativa

| | Robotium | UIAutomator | Espresso | Appium | Calabash | Monkey |
| Android | Sí | Sí | Sí | Sí | Sí | Sí |
| iOS | No | No | No | Sí | Sí | No |
| Web mòbil | Sí (Android) | Limitat en clics | Sí (mitjançant un paquet) | Sí (Android i iOS) | Sí (Android) | Sí |
| Llenguatge | Java | Java | Java | Gairebé tots | Ruby | Terminal |
| Eines de creació de test | Testdroid Recorder | UI Automator Viewer | Hierarchy Viewer | Appium.app | CLI | Terminal |
| Versions de API suportats | Totes | 18 => | 8, 10, 15 => | Totes | Totes | Totes |
| Comunitat | Contribuïdors | Google | Google | Activa | Poc activa | Google |

## Enllaços externs

* Android Developer - Testing Support Library
* What is Appium - Appium for Android
* Introduction to Appium's Philosophy, Design and Concepts

## Referències

* ↑ «Building Local Unit Tests» (en anglés). Android Developers, -. [Consulta: 18 octubre 2016].
* ↑ «Testing Support Library Setup» (en anglés). Android Developers, -. [Consulta: 20 decembre 2016].
* ↑ «AndroidJUnitRunner» (en anglés). Android Developers, -. [Consulta: 20 decembre 2016].
* ↑ «Espresso» (en anglés). Android Developers, -. [Consulta: 20 decembre 2016].
* ↑ «UI Automator» (en anglés). Android Developers, -. [Consulta: 20 decembre 2016].
* ↑ «Mock Android Dependencies» (en anglés). Android Developers, -. [Consulta: 20 decembre 2016].
* ↑ «Test Your App» (en anglés). Android Studio, -. [Consulta: 18 octubre 2016].
* ↑ «Building Instrumented Unit Tests» (en anglés). Android Developers, -. [Consulta: 20 decembre 2016].
* ↑ «Getting Started with Testing» (en anglés). Android Developers, -. [Consulta: 26 octubre 2016].
* ↑ «ActivityTestRule» (en anglés). Android Developers, -. [Consulta: 26 octubre 2016].
* ↑ «Create and Edit Run/Debug Configurations» (en en). Google. [Consulta: 20 de desembre de 2016].
* ↑ «Robotium Recorder» (en anglés). Robotium, -. [Consulta: 18 octubre 2016].
* ↑ «5 Best Automation Tools for Testing Android Applications» (en anglés). Software Testing Help, 25 d'agost de 2016. [Consulta: 20 octubre 2016].
* ↑ «Software Testing Help» (en anglés). Android Developer, -. [Consulta: 20 octubre 2016].
* ↑ «Espresso» (en anglés). Android Testing Support Library. [Consulta: 20 octubre 2016].
* ↑ «Testing UI for a Single App» (en anglés). Android Developers, 19 de març de 2015. [Consulta: 20 octubre 2016].
* ↑ «Calabash» (en anglés). Calabash, -. [Consulta: 24 octubre 2016].
* ↑ «UI/Application Exerciser Monkey» (en anglés). Google, -. [Consulta: 20 desembre 2016].
* ↑ «Espresso Web» (en anglés). Android Testing Support Library. [Consulta: 21 octubre 2016].