Functioneel testen van een Android app – Een vergelijking van vier test frameworks

Het toepassen van functioneel testen is geen nieuwe methodiek meer bij het
ontwikkelen van Java programmatuur. Het schrijven van functionele tests maakt het mogelijk inzicht te krijgen in de stabiliteit van een applicatie of systeem, bij code wijziging of uitbreiding. Maar hoe zit het met het functioneel testen van een Android applicatie? In dit artikel lichten we vier test frameworks toe, die gebruikt kunnen worden voor het functioneel testen van een Android applicatie.

“En, werkt de applicatie nog?” is de vraag die ontwikkelaars moeten kunnen beantwoorden als er een uitbreiding of verbetering heeft plaatsgevonden. Dit geldt ook bij het ontwikkelen van een Android applicatie. Ook het gebruik van TDD (Test Driven Development), waarbij eerst de test wordt geschreven waarna de code volgt, is gewenst. Zelfs het toepassen van geautomatiseerd functioneel testen is niet meer weg te denken. Het toepassen van bijvoorbeeld Selenium en Fitnesse voor het testen van een Java Web applicatie, in combinatie met Jenkins is normaal voor de meeste Java ontwikkelaars.

De verwachting is dus dat dit ook een bewezen techniek is bij het ontwikkelen van Android applicaties. Helaas is dit (nog) niet het geval. Door de relatieve snelle groei van Android zijn deze methodieken niet goed uit ontwikkeld en is hier een inhaalslag gaande. De ambitie is er wel, gezien de hoeveelheid functionele test frameworks die gebruikt kunnen worden, maar dit gaat ten koste van de kwaliteit en toepasbaarheid van deze frameworks. Maar wat zijn de meest gebruikte functionele test frameworks?

Bij het bespreken van de frameworks wordt installatie niet besproken. Aan de hand van een codevoorbeeld wordt uitgelegd wat de voor- en nadelen zijn van het specifieke framework.

De Android applicatie (1) die getest wordt is een simpele rekenmachine applicatie. Het testscenario zal een optelling zijn, waarbij getest wordt of ‘1’ + ‘3’ een resultaat van ‘4’ geeft.

UIAutomator
Het door Google zelf uitgebrachte test framework UIAutomator (2) maakt het mogelijk om in Java (en JUnit) functionele tests te schrijven. Het framework is niet gebonden aan de test applicatie zelf maar kan ook beschikken over het platform van de Android telefoon. Zo is het ook mogelijk vanuit je test de instellingen van het device (emulator of fysieke telefoon) aan te passen. Dit maakt het mogelijk om te testen wat het gedrag van de applicatie is bij bijvoorbeeld het uitzetten van je internet verbinding of het wisselen van je account.


UiObject allAppsButton = new UiObject(new UiSelector().description("Apps"));
allAppsButton.clickAndWaitForNewWindow();
UiObject appsTab = new UiObject(new UiSelector().text("Apps"));
appsTab.click();
UiScrollable appViews = new UiScrollable(new UiSelector().scrollable(true));
appViews.setAsHorizontalList();
UiObject calculatorApp = appViews.getChildByText(new
UiSelector().className(android.widget.TextView.class.getName()), "Calculator app");
calculatorApp.clickAndWaitForNewWindow();
UiObject oneButton = new UiObject(new UiSelector().text("1"));
oneButton.click();
UiObject plusButton = new UiObject(new UiSelector().text("+"));
plusButton.click();
UiObject threeButton = new UiObject(new UiSelector().text("3"));
threeButton.click();
UiObject eqButton = new UiObject(new UiSelector().text("="));
eqButton.click();
UiObject text = new UiObject(new UiSelector().className("android.widget.EditText").text("4"));
assertTrue(text.exists());

 

Helaas is het nog een relatief nieuw framework dus er is weinig documentatie beschikbaar. Ook zal het uitvoeren van de geschreven tests alleen op een device uitgevoerd kunnen worden die Android 4.1 of hoger ondersteunen.

In het kort:


+ Volledig controle over device
+ Code geschreven in Java
- Alleen voor Android 4.1 en hoger
- Weinig documentatie voor handen

 

Robolectric
Het op Java gebaseerde test framework Robolectric (3) is qua performance de beste van de betere geteste frameworks. Dit komt omdat het niet op een device draait, maar op een niet visuele UI simulator. Hierdoor wordt de vertragende factor van het starten van een emulator of het installeren op een fysieke telefoon weggenomen. Dit maakt dat Robolectric een goede keuze bij TDD.


@RunWith(RobolectricTestRunner.class)
public class MainActivityTest
{
private MainActivity _activity;
@Before
public void setUp() throws Exception
{
_activity = Robolectric.buildActivity(MainActivity.class).create().get();
}
@Test
public void testAdding() throws Exception
{
Button btnOne = (Button) _activity.findViewById(R.id.num_1);
Button btnAdd = (Button) _activity.findViewById(R.id.op_add);
Button btnThree = (Button) _activity.findViewById(R.id.num_3);
Button btnEquals = (Button) _activity.findViewById(R.id.op_equ);
btnOne.performClick();
btnAdd.performClick();
btnThree.performClick();
btnEquals.performClick();
EditText resultText = (EditText) _activity.findViewById(R.id.editText1);
assertEquals("4", resultText.getText().toString());
}
}

 

Doordat Robolectric gebruikt maakt van een niet visuele UI simulator, is dus niet mogelijk om een test uit te voeren voor een specifiek probleem op bijvoorbeeld een Samsung device.

In het kort:


+ Goede performance
- Kan niet uitgevoerd worden op een device

 

Robotium
De gedachte achter Robotium (4) is dat de functionele test een (simpele) beschrijving is van wat de gebruiker ziet en doet. Dit maakt het framework een goede keus bij “blackbox” testen. Tevens is er uitgebreide documentatie beschikbaar, zijn er goede voorbeelden te vinden en is de API eenvoudig te gebruiken.


public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity>
{
private Solo _solo;
public MainActivityTest()
{
super(MainActivity.class);
}
@Override
protected void setUp() throws Exception
{
super.setUp();
_solo = new Solo(getInstrumentation(), getActivity());
}
public void testAdding()
{
_solo.assertCurrentActivity("Is app started", MainActivity.class);
_solo.clickOnButton("CLR");
_solo.clickOnButton("1");
_solo.clickOnButton("+");
_solo.clickOnButton("3");
_solo.clickOnButton("=");
EditText editText = (EditText)
getActivity().findViewById(com.elsinga.calculator.R.id.editText1);
assertEquals("4", editText.getText().toString());
}
}

 

In het kort:


+ Goed gedocumenteerd
+ Goed voor “blackbox” testen
+ Wat je ziet kan je testen

 

Calabash-Android
Net zoals Robotium is bij Calabash-Android (5) de functionele test beschreven in wat de gebruiker ziet en doet. Het enige verschil is dat de tests niet geschreven zijn in Java maar in Cucumber (6), een text-based structuur. Dit maakt het mogelijk dat de functionele tests gemaakt kunnen worden door niet ontwikkelaars. Doordat de test niet in Java is geschreven, is het ‘debuggen’ van een falende test helaas niet mogelijk.


Feature: Adding
Scenario: add
I should see "1"
Then I press "1"
And I press "+"
And I press "3"
And I press "="
Then I see "4"

 

In het kort:


+ Goed gedocumenteerd
+ Testen kunnen geschreven worden door niet techneuten
+ Wat je ziet kan je testen
- ‘Debuggen’ van de test is niet mogelijk

 

Tot slot
Het functioneel testen van Android applicaties is mogelijk. Welk test framework toegepast kan worden is afhankelijk van de wensen van de ontwikkelaar en/of organisatie. Vragen die daarbij spelen zijn: wie gaat de tests maken, wat moet er getest worden en/of op welk device worden de tests gedraaid. Desalniettemin is er genoeg keuze om te starten met schrijven van functionele tests.

Referenties

(1) Voorbeeld applicatie

(2) UIAutomator

(3) Robolectric

(4) Robotium

(5) Calabash-Android

(6) Cucumber