Testen op fysieke mobiele devices

Testen op mobiele devices is tegenwoordig steeds makkelijker door de komst van open source frameworks, zoals Appium. Koppel een mobiel device aan je laptop en je kunt met Appium het device geautomatiseerd testen. Simpel, maar hoe schaal je dit naar meerdere devices met parallelle testuitvoering? Zelf een device lab opzetten met een Selenium Grid of toch het device management overlaten aan een cloud leverancier? In dit artikel kijken we naar de voor- en nadelen van zowel een eigen device lab als in de cloud.

Open-source test framework Appium

Het standaard framework voor het testen van mobiele devices is momenteel Appium. Met Appium heb je de mogelijkheid om het volgende te testen:

  • Native Apps voor iOS en Android;
  • Mobile Web Apps via de mobiele browser (Safari voor iOS en Stockbrowser, Chrome op Android);
  • Hybrid Apps, een native wrapper om de webview heen voor interactie tussen de app / device en de webcontent, bijvoorbeeld met Phonegap / Cordova / Crosswalk;
  • Windows 10 Desktop Apps;
  • Robots, zoals Tapster.

 

Het voordeel van Appium is dat je gebruik kunt maken van Selenium WebDriver, het de facto standaard voor het automatiseren van webtesten. Met Appium kun je naast de standaard WebDriver commando’s ook device-specifieke zaken automatiseren, zoals hardware buttons van een mobiel device en swipe/tap acties.

Hieronder is een voorbeeld van een simpele test op Chrome op een Android device met de standaard Selenium WebDriver commando’s in combinatie met een Appium commando om de Android back button aan te sturen. Links is een test opzet voor webbrowser met een lokaal grid en rechts een opzet met Appium. Zoals je kunt zien, verschilt de opzet voor devices (Appium) minimaal ten opzichte van de opzet voor web.

 

 

 

public class WebTest {

 

    private static RemoteWebDriver driver;

    private static final String serverURL = "http://127.0.0.1:4444/wd/hub";

 

    By searchInput = By.id("searchInput");

    By submitButton = By.cssSelector(".pure-button");

    By pageTitle = By.tagName("h1");

    By logo = By.cssSelector((".central-textlogo"));

 

    @Before

    public void setUp() throws MalformedURLException {

        DesiredCapabilities capabilities = new DesiredCapabilities();

 

 

 

 

 

        capabilities.setCapability("browserName", "Chrome");

 

        driver = new RemoteWebDriver(new URL(serverURL), capabilities);

    }

 

    @Test

    public void test() {

        driver.get("http://www.wikipedia.org");

        driver.findElement(searchInput).sendKeys("Java");

        driver.findElement(submitButton).click();

        Assert.assertEquals("Java", driver.findElement(pageTitle).getText())

        // Browser back navigatie

        driver.navigate().back();

        Assert.assertEquals(true, driver.findElement(logo).isDisplayed());

    }

 

    @After

    public void tearDown() {

        driver.quit();

    }

}

public class MobileTest {

 

    private static AndroidDriver driver;

    private static final String serverURL = "http://127.0.0.1:4723/wd/hub";

 

    By searchInput = By.id("searchInput");

    By submitButton = By.cssSelector(".pure-button");

    By pageTitle = By.tagName("h1");

    By logo = By.cssSelector((".central-textlogo"));

 

    @Before

    public void setUp() throws MalformedURLException {

        DesiredCapabilities capabilities = new DesiredCapabilities();

 

        capabilities.setCapability("deviceName", "Nexus 5");

        capabilities.setCapability("platformName", "Android");

        capabilities.setCapability("browserName", "Chrome");

 

        driver = new AndroidDriver(new URL(serverURL), capabilities);

    }

 

    @Test

    public void test() {

        driver.get("http://www.wikipedia.org");

        driver.findElement(searchInput).sendKeys("Java");

        driver.findElement(submitButton).click();

        Assert.assertEquals("Java", driver.findElement(pageTitle).getText());

        // Android back button

        driver.pressKeyCode(4);

        Assert.assertEquals(true, driver.findElement(logo).isDisplayed());

    }

 

    @After

    public void tearDown() {

        driver.quit();

    }

}

Listing 1

 

Een ander voorbeeld wat je met Appium kunt uitvoeren, is het swipen op het scherm:

 

 

        // Schermgrootte

        Dimension size = driver.manage().window().getSize();

        // Swipe startpunt: onderin het scherm

        int startY = (int) (size.height * 0.80);

        // Swipe eindpunt: bovenin het scherm

        int endY = (int) (size.height * 0.20);

        // Horizontale as voor het swipen: midden van het scherm

        int startEndX = size.width / 2;

 

        // Swipe van onder naar boven

        driver.swipe(startEndX, startY, startEndX, endY, 3000);

        //Swipe van boven naar onder

        driver.swipe(startEndX, endY, startEndX, startY, 3000);

Listing 2

 

Appium lokaal opzetten

De documentatie van Appium is vrij uitgebreid en te vinden op https://github.com/appium/appium. Binnen 15 minuten kun je al je eerste testen schrijven op een Android emulator of een Apple simulator. Een emulator / simulator zegt echter niets over de performance van de Native / Hybrid / Web App en geeft alleen een goed beeld over de functionele flow. App "conditions" zijn beter te testen op fysieke devices. In het vervolg van dit artikel gaan we daarom uit van fysieke devices.

 

Zelf een device lab opzetten

Als je Appium op je lokale machine werkend hebt gekregen, is de overgang naar een eigen device lab geen grote stap meer.

 

Benodigdheden:

  • Eén of meerdere Mac-mini's met XCode, afhankelijk hoeveel iOS devices je wilt koppelen
  • iOS developer license om zowel een app te kunnen installeren als Safari te kunnen gebruiken, zie: "Issues uit de praktijk"’;
  • Android SDK;
  • Selenium Grid;
  • Appium;
  • USB-hubs met power support en sync mogelijkheid;
  • Kwalitatief goede mini-usb / Apple usb kabels.

 

Optioneel:

  • Kabel management (wordt al snel spaghetti);
  • KVM switch om gemakkelijk tussen meerdere Mac-mini's te switchen;
  • Houders / standaards voor de devices.

 

Alle processen zijn verder te automatiseren (configureren Selenium Grid hub / nodes met bijvoorbeeld  Ansible playbooks), maar voor het gemak worden alle stappen hier vanuit de basis behandeld.

 

Hoe op te zetten?

Uitgaande dat benoemde benodigdheden zijn uitgevoerd, kan je met 3 simpele stappen in korte tijd fysieke devices koppelen aan een Mac Mini in een Grid en direct met Appium testen op devices.

 


  1. Start een Selenium Grid:

java -jar selenium-server-standalone.jar -role hub

  1. Configureer de nodes in een Appium node configuratie bijvoorbeeld genaamd nodeConfig.json voor de devices:

{ "capabilities": [{ "platformName": "Android", "deviceName": "Nexus 7", "browserName": "chrome", "version": "7.1.1", "maxInstances": 1, "platform": "MAC" } ], "cleanUpCycle": 2000, "timeout": 30000, "url": "<appium_host_name>:<appium_host_port>/wd/hub", "host": "<appium_host_name>", "port": <appium_host_port>, "maxSession": 1, "register": true, "registerCycle": 5000, "hubPort": <hub_host_port>, "hubHost": "<hub_host_name>" }

  1. Start Appium met het configuratiebestand waardoor de nodes direct aangemeld worden op de hub:

appium -p <appium_host_port> –-nodeConfig nodeConfig.json

Listing 3

 

Issues vanuit de praktijk

Met een eigen device lab hebben we een aantal maanden gedraaid bij een grote bank. Hierbij kwamen we de volgende uitdagingen tegen:

  • Speciale builds voor iOS, de gebruikte devices zullen geregistreerd moeten zijn in de build license

Voor het ontwikkelen van een iOS app heb je een Apple Developer ID en een geldig Developer Account met een correct geconfigureerde distribution certificate and provisioning profile nodig. In het kort betekent dit dat je met je Developer Account de iOS app moet "ondertekenen met een geldig bewijs dat de app op een of meerdere toegewezen Apple toestellen mag worden geïnstalleerd". Doe je dit niet met je app, dan kun je hem niet installeren op een device en niet testen met Appium. Zie ook: https://github.com/appium/appium/blob/master/docs/en/appium-setup/real-devices.md

Ieder nieuw aangeschaft device moet worden toegewezen aan het Developer account.

  • Geen support voor Crosswalk door Appium

Niet iedere Android telefoon heeft dezelfde webview. Er zit verschil tussen Android 4.0-4.4, 5, 6 etc. met als gevolg dat de CSS en Javascript van de hybride app verschillend geparsed worden. Om dit op ieder device gelijk te houden, zijn wij voor Android overgestapt naar Crosswalk. Met Crosswalk Apps wordt de webview (Chromium) standaard meegeleverd waardoor je als ontwikkelaar niet druk hoeft te maken over de JS / CSS ondersteuning, zie ook: https://crosswalk-project.org/. Nadeel van deze keuze was dat Appium geen support heeft voor Crosswalk waardoor Appium niet gebruikt kan worden voor het automatiseren van de Android apps.

  • Stroomvoorziening van tablets

Telefoons die aan de normale stroomvoorziening zijn aangesloten krijgen over het algemeen voldoende stroom om continu testen erop te draaien. Bij tablets is dat echter een uitdaging vanwege de benodigde hoeveelheid stroom (2100mA). Een kwalitatief goede USB-hub kan dit probleem verhelpen.

  • Loskomende en flikkerende schermen bij continu draaien

Als we de stroomvoorziening onder controle hebben, dan komen we bij de volgende hardware uitdaging. We hebben een aantal telefoons continu aangesloten en dagelijks testen erop laten draaien. Na een aantal weken kwamen bij sommige devices de schermen los / gingen de batterijen uitzetten. 

De softwarematige werking ten behoeve van testen is echter nog wel intact, maar het is natuurlijk een kwestie van tijd dat de toestellen softwarematig tevens niet meer te benaderen zijn door de hardware beperkingen. Een ander veelvoorkomend fenomeen zijn flikkerende schermen. Hierbij is het tevens softwarematig geen issue, maar als je fysiek naar het scherm van het device kijkt, dan flikkert het scherm continu. Reden hiervoor is dat de devices 24/7 standby moeten staan (voor Android de optie Stay awake in de developer options)

  • Stabiliteit en connectieproblemen

Het is een uitdaging om toestellen stabiel te houden. In onze ervaring hebben we gezien dat na iedere paar dagen connectieproblemen optreden waardoor we geen stabiele 24/7 oplossing konden vinden. De toestellen moeten dan herstart en opnieuw aangemeld worden op het Grid. Uiteraard kun je dit automatiseren, maar het zoeken naar de optimale frequentie van herstarten/herconfigureren per device verdient een eigen onderzoek.

  • Crosswalk ondersteuning

Met een eigen device lab ben je gebonden aan Appium en hierbij heb je ook direct te maken met haar beperkingen. Crosswalk wordt momenteel niet ondersteund. Wellicht komt de ondersteuning nog in de toekomst aangezien Crosswalk een relatief nieuwe toepassing is. Bepaal goed welke type apps je wilt testen voordat je begint met het opzetten van een eigen device lab.

 

Testen in de cloud

Vanwege de genoemde uitdagingen met een eigen device lab zijn we overgestapt naar een cloud leverancier.

 

Welke cloud leveranciers?

Device testing in de cloud is mogelijk met verschillende aanbieders. De marktleiders van testen op ‘echte’ devices in cloud zijn Sauce Labs en Perfecto Mobile. De mogelijkheden voor automatisering zijn bij Sauce Labs volledig gebaseerd op Appium. Zonder problemen kun je gebruik maken van de Appium API voor je testen. Perfecto Mobile biedt een eigen Selenium implementatie aan die de Appium API ondersteund, maar ook een aantal extra functionaliteiten heeft, zoals:

  • Crosswalk ondersteuning;
  • Automatiseren op basis van OCR. Er wordt dan in dit geval een screen capture gemaakt van het device en met behulp van OCR gescand op tekst die je opgeeft. Met de gevonden tekst kun je dan je gebruikelijke kliks of assertions doen. Dit is makkelijk wanneer je te maken hebt met meerdere web/native-views in je app of als een specifiek element lastig uniek te pinpointen is met standaard WebElementen.

 

Hoe connectie maken?

Gebruik maken van een cloudoplossing is over het algemeen vrij simpel. Je kunt het zien als een ander endpoint waarmee je connectie maakt, dus niet veel anders dan een eigen Selenium Grid. Afhankelijk van de cloud leverancier kan het voorkomen dat er één of twee extra WebDriver-capabilities toegevoegd moeten worden aan de device configuratie.

 

Voordelen en aandachtspunten

Testen in de cloud heeft een aantal voordelen:

  • Device management wordt uitgevoerd door de leverancier. De genoemde uitdagingen zijn voor rekening van de leverancier en hier zijn cloud leveranciers in gespecialiseerd.
  • Admin panel voor device reboots, (hard) resets, reserveringen, user/autorisatiemanagement etc. Zeker bij veel gebruik door verschillende gebruikers is een reserveringssysteem erg handig.
  • SLA afspraken over uptime en support.
  • Cloud leveranciers, met een eigen Selenium implementatie, kunnen sneller iOS / Android updates supporten dan Appium (bijv. van iOS 9 naar 10).
  • Focus op ontwikkelen van je eigen software (apps) in plaats van ook nog rekening houden met device management wat vaak een bijzaak is bij grotere organisaties.

 

De aandachtspunten bij cloud leveranciers zijn:

  • Relatief duur. Een eigen device lab is daarentegen ook niet goedkoop als je kijkt naar onderhoud en stabiliteitsuitdagingen gezien de benodigde effort en vervanging van devices.
  • Nieuwe features die je nodig hebt in de cloud worden geprioriteerd met features die andere klanten nodig hebben. Hierdoor kan het een uitdaging zijn om features hoog op de backlog van de leverancier te krijgen.
  • Verschillende tijdzones bij support. Bij issues worden de juiste support / R&D engineers aangehaakt door de leverancier die verspreid zijn over de wereld en dus in andere tijdzones zijn. Concreet kan dit betekenen dat in het geval van een blocking issue in de ochtend, het pas in de middag opgepakt wordt omdat de betreffende engineer(s) in de VS werken.
  • Cloud leveranciers met een eigen Selenium implementatie ondersteunen niet altijd de laatste versie van Selenium / Appium.

 

Advies bij het selecteren van een cloud leverancier

Voer altijd eerst een POC uit met een cloud leverancier om te zien of de app die je wilt testen ook goed werkt in de cloud met de ondersteunde API’s. Daarnaast kun je tijdens de POC ook ervaren hoe het contact en ondersteuning is met de leverancier. Vaak zitten de support engineers overal en nergens waardoor hun beschikbaarheid beperkt is vanwege de verschillende tijdzones.

 

Conclusie

Een eigen device lab opzetten is bijzonder leerzaam, maar vooral bedoeld voor kleinschalige device testen. Hierbij bedoelen we een paar gebruikers die af en toe een test draaien op devices. Indien je te maken hebt met vele gebruikers/teams die device testing als onderdeel van de continuous delivery straat zien, dan is een cloud leverancier een betere optie. Niet alleen worden de stabiliteitsuitdagingen, die je bij een eigen device lab hebt, weggenomen, maar bij een cloudoplossing heb je beschikking over functionaliteit zoals usermanagement en hard resets op afstand.

 


 Zie voor documentatie over het Selenium project en het Selenium Grid: http://www.seleniumhq.org/