Connect(); 2016

Band 31, Nummer 12

Connect(); Tests für mobile Apps: Skalieren der automatisierten Tests mobiler Apps mit Xamarin Test Cloud

Von Justin Raczak; 2016

In den letzten Jahren hat sich die Weise, in der Teams Software entwickeln und verteilen, dramatisch verändert. Wo einst die Meinung vorherrschte, dass langwierige Definitionsprozesse von Lastenheften die Bereitstellung eines perfekten Produkts mit dem ersten Release sicherstellen könnte, ist nun klar geworden, dass der Schlüssel zum Erfolg in steilen Lernkurven mit schneller Abfolge von Schritten liegt. Wie sich das Denken ändert, müssen sich auch die Workflows ändern. Entwicklungszyklen, die Monate oder Jahre dauern, und an die sich langwierige Wasserfallphasen der Qualitätssicherung anschließen, machen steile Lernkurven schwer erreichbar. Rückkopplungsschleifen müssen verkürzt und kleine Änderungen schnell implementiert und für Benutzer freigegeben werden. Eine prompte Bereitstellung lässt sich nur erreichen, wenn der gute Zustand der Software jederzeit sichergestellt ist. Die Automatisierung von Tests ermöglicht das.

Mithilfe von automatisierten Tests können Sie Ihre Apps in einer Weise testen, für die bisher Tage oder Wochen erforderlich waren. Anstatt bis zum Ende eines Sprints zu warten, der sich aus mehreren hundert neuen Codezeilen zusammensetzt, können Sie kleine Änderungen testen, wie sie bei jedem Commit hinzugefügt werden. Durch dieses fortlaufende Testen machen sich Defekte gleich bei ihrer Einführung bemerkbar – so verringert sich der Zeitaufwand für ihre Beseitigung. Und da das Verhalten der App ständig überprüft wird, bildet sich das nötige Vertrauen, mit der Auslieferung an Benutzer zu beginnen, sobald Sie bereit sind. Automatisierte Tests eröffnen den Zugang zu einer Welt, in der Sie Defekte noch am Tag ihrer Entdeckung beheben. Das mobile Ökosystem hält mit seiner bunten Vielfalt an mobilen Geräten und Betriebssystemanbietern jedoch auch einzigartige Herausforderungen bereit.

Durch die Xamarin Test Cloud wird das Skalieren Ihrer automatischen Tests mit nur minimalen Änderungen an den vorhandenen Workflows schnell und einfach. Mit mehr als 400 verschiedenen Gerätekonfigurationen ermöglicht Ihnen Test Cloud ohne den Kosten- und Verwaltungsaufwand, den Aufbau und Unterhalt eines eigenen Gerätelabors mit sich bringen, das Überprüfen des Verhaltens Ihrer App auf den Gerätemodellen und in den Betriebssystemversionen, die für Ihre Benutzer wichtig sind. In den meisten Fällen können Sie diesen enormen Vorteil ohne oder mit allenfalls geringen Änderungen am Code nutzen.

Test Cloud unterstützt das Erstellen von Tests in C# (UITest), Ruby (Calabash) und Java (Appium und Espresso). In dem Teil dieses Artikels, der sich mit Projektänderungen befasst, lege ich den Schwerpunkt auf den besonders stark nachgefragten Frameworkzusatz Appium mit JUnit und durchlaufe schrittweise die erforderlichen Änderungen an Ihrem Projekt, damit Sie Ihre vorhandenen Tests in Test Cloud ausführen können. Ferner werfe ich einen Blick auf die Weboberfläche, auf der Sie Ihre Testergebnisse überprüfen und Probleme bei Tests mit Fehlern beheben können. Die spezifischen Änderungen, die erforderlich sind, können sich im Lauf der Zeit ändern. Die aktuelle Version dieser Anweisungen finden Sie unter bit.ly/2dhp2VQ.

In diesem Beispiel wird von den folgenden Voraussetzungen ausgegangen:

  • Einem aktiven Test Cloud-Konto (registrieren Sie sich unter bit.ly/2e3YgTy)
  • Einem installierten Befehlszeilentool (Anweisungen finden Sie unter bit.ly/2dcrbXS)
  • Einem nativen Android-Anwendungsprojekt
  • Einer vorhandenen Sammlung Appium-Tests, die mithilfe von JUnit (mindestens Version 4.9) erstellt wurden und mit Appium 1.5 kompatibel sind
  • Einem Maven-Buildsystem (mindestens Version 3.3.9)

Änderungen am Buildsystem

Damit Sie mit der Verwendung von Test Cloud beginnen können, müssen Sie zuerst die Abhängigkeit hinzufügen, um sicherzustellen, dass die Vorbereitungsaufgaben für die erforderlichen Dateien für Ihren Build zur Verfügung stehen.

Hinzufügen der Test Cloud-Abhängigkeit Um Test Cloud in Ihr Projekt einzubeziehen und sicherzustellen, dass die erweiterten Android- und iOS-Treiber zur Kompilierzeit verfügbar sind, fügen Sie Ihrer pom.xml-Datei die folgende Abhängigkeit hinzu:

<dependency>
  <groupId>com.xamarin.testcloud</groupId>
  <artifactId>appium</artifactId>
  <version>1.0</version>
</dependency>

Hinzufügen des Uploadprofils Fügen Sie Ihrer pom.xml-Datei das Profil aus Abbildung 1 im <profiles>-Tag hinzu. Wenn noch kein Abschnitt <profiles> vorhanden ist, erstellen Sie ihn, und fügen Sie das Profil hinzu. Dieses Profil packt Ihre Testklassen und alle Abhängigkeiten in den Ziel-/Uploadordner, aus dem sie anschließend auf Test Cloud hochgeladen werden können.

Abbildung 1 Test Cloud-Uploadprofil

<profile>
  <id>prepare-for-upload</id>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}
                /upload/dependency-jars/</outputDirectory>
              <useRepositoryLayout>true</useRepositoryLayout>
              <copyPom>true</copyPom>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-pom-file</id>
            <phase>package</phase>
            <goals>
              <goal>testResources</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}
                /upload/</outputDirectory>
              <resources>
                <resource>
                  <directory>
                    ${project.basedir}
                  </directory>
                  <includes>
                    <include>pom.xml</include>
                  </includes>
                </resource>
              </resources>
            </configuration>
          </execution>
          <execution>
            <id>copy-testclasses</id>
            <phase>package</phase>
            <goals>
              <goal>testResources</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}
                /upload/test-classes</outputDirectory>
              <resources>
                <resource>
                  <directory>
                    ${project.build.testOutputDirectory}
                  </directory>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</profile>

Änderungen an den Tests

Nachdem Sie Ihren Build jetzt konfiguriert haben, müssen Sie Ihre Testklassen ändern, um die Text Cloud-Java-Erweiterungen nutzen zu können.

Hinzufügen der Imports zu den Testklassen Importieren Sie die folgenden Pakete in Ihre Testklassen:

import com.xamarin.testcloud.appium.Factory;
import com.xamarin.testcloud.appium.EnhancedAndroidDriver;
import org.junit.rules.TestWatcher;
import org.junit.Rule;

Instanziieren von TestWatcher Fügen Sie diese Instanziierung in eine Ihrer Testklassen ein:

@Rule
public TestWatcher watcher = Factory.createWatcher();

Aktualisieren Ihrer Treiberdeklarationen Ersetzen Sie jede Deklaration von „AndroidDriver<MobileElement>“ durch „EnhancedAndroidDriver­<MobileElement>“, wie hier dargestellt:

private static EnhancedAndroidDriver<MobileElement> driver;

Aktualisieren Ihrer Treiberinstanziierungen Ersetzen Sie jede Instanziierung Ihres Treibers so, dass aus jeder Zeile in dieser Form:

Driver = new AndroidDriver<MobileElement>(url, capabilities);

eine Zeile in dieser Form wird:

Driver = new EnhancedAndroidDriver<MobileElement>(url, capabilities);

Der erweiterte Treiber erlaubt Ihnen, die Schritte in Ihrem Text mithilfe von driver.label(„MeinTestSchrittBezeichnung“) zu bezeichnen. Diese Methode erzeugt eine Bezeichnung für den Testschritt und einen begleitenden Screenshot, der im Testbericht in Test Cloud angezeigt wird. Ich empfehle, die Bezeichnung in der @After-Methode aufzurufen, die einen Screenshot der App in ihrem finalen Zustand erfasst, bevor der Test abgeschlossen wird. Der Screenshot wird auch dann erstellt, wenn beim Test ein Fehler auftritt, was wertvolle Einblicke in die Fehlergründe geben kann. Praktisch könnte das etwa so aussehen:

@After
  public void tearDown(){
    driver.label("Stopping app");
    driver.quit();
  }

Hochladen auf Test Cloud

Da Ihr Projekt jetzt über alle Voraussetzungen verfügt, können Sie Ihre Dateien vorbereiten und sie in Test Cloud ausführen. Bevor Sie mit den Uploadschritten fortfahren, empfiehlt es sich, eine lokale Ausführung zu versuchen, um zu überprüfen, ob alles wie erwartet funktioniert. Wenn Sie Probleme bei den soeben vorgenommenen Konfigurationsänderungen beheben müssen, lässt sich das lokal viel schneller erledigen.

Um ihre Testklassen und alle Abhängigkeiten in den Ziel-/Uploadordner zu packen, führen Sie den folgenden Befehl aus:

mvn –DskipTests -P prepare-for-upload package

Es ist sinnvoll, das Vorhandensein des Ziel-/Uploadverzeichnisses im Stammordner Ihres Projekts zu überprüfen, um sicherzustellen, dass Sie für den Upload bereit sind. Wenn es sich um eine neue App in Test Cloud handeln soll, müssen Sie die App im Rahmen des Testlaufs erstellen. Folgen Sie dem Workflow, um einen neuen Testlauf zu erstellen, für den Sie Ihre Geräte auswählen, die Einstellungen festlegen und den Befehl erstellen, den Sie für die Ausführung des Testlaufs benötigen. Für die Zwecke dieser Übung ist es angebracht, eine kleine Anzahl Geräte aus der Kategorie „Tier 1“ (Ebene 1) auszuwählen, damit Ihre Ergebnisse schnell zur Überprüfung bereit sind. Kopieren Sie den erzeugten Befehl, und führen Sie ihn auf der Befehlszeile aus.

Sobald der Dateiupload erfolgreich ausgehandelt und überprüft wurde, werden die Geräte bereitgestellt, Ihre App wird installiert, und Ihre Tests werden ausgeführt. Das Betriebsmodell von Test Cloud baut auf der parallelen Ausführung von Geräten auf, also der Anzahl physischer Geräte, die parallel verwendet werden können. Beispielsweise kann ein Benutzer mit fünf parallel ausgeführten Geräten seine App zur gleichen Zeit auf Nexus 5X, Nexus 6P, Samsung Galaxy S5, Samsung Galaxy S6 und HTC M8 testen. Diese Effizienz ist einer der bedeutendsten Vorzüge von Test Cloud und erlaubt Ihnen, Ihre Abdeckung auf einfache Weise zu erweitern, um mehr Geräte zu umfassen, ohne dadurch nennenswert oder überhaupt zusätzliche Wartezeit zu verursachen.

Das Befehlszeilentool streamt Updates zum Status des Testlaufs und stellt Ihnen einen Link zum Testbericht zur Verfügung, sobald der Testlauf abgeschlossen ist. Folgen Sie dem bereitgestellten Link zum Testbericht, um Ihre Ergebnisse zu untersuchen.

Es gibt drei Granularitätsstufen, in denen Sie die Ergebnisse anzeigen können:

  • Übersichtsbericht.
  • Geräteraster.
  • Gerätedetailbericht.

Ich gehe der Reihe nach auf sie ein.

Der Übersichtsbericht Die Übersicht bietet Ihnen zusammengefasste Informationen über einen Testlauf einschließlich Details zum erfolgreichen/fehlerhaften Abschluss, Fehlerstatistiken getrennt nach Betriebssystemversion, Hersteller und Formfaktor sowie Details zur eigentlichen Ausführung, einschließlich der Konfiguration der Zielgeräte und der gesamten Ausführungszeit (siehe Abbildung 2).

Der Übersichtsbericht
Abbildung 2 Der Übersichtsbericht

Bei Fehlern in Ihren Testlaufprozeduren möchten Sie vermutlich tiefer graben, um die Grundursachen zu untersuchen und Daten fürs Debuggen zu sammeln. Das Geräteraster bildet die nächste Detailstufe.

Das Geräteraster Das Geräteraster stellt in Kombination mit den bei jedem einzelnen Schritt erfassten Screenshots einen sehr effizienten Mechanismus für das schrittweise Navigieren in Ihren Testergebnissen dar. Anhand der in den Testschritten klar gekennzeichneten Fehler können Sie schnell zu einem Schritt mit Fehler gelangen und den visuellen Status Ihrer App auf jedem Gerät untersuchen. Bei größeren Gerätesammlungen können Sie die angezeigten Geräte für die Untersuchung durch Filtern auf die eingrenzen, die nicht mit einem aufgeräumten Gesamtergebnis abgeschlossen haben. Wenn die Fehlerursache bei dieser Detailstufe nicht erkennbar ist, können Sie um eine weitere Stufe verfeinern, um die Gerätedetails anzuzeigen (siehe Abbildung 3).

Der Geräterasterbericht
Abbildung 3 Der Geräterasterbericht

Der Gerätedetailbericht Die Gerätedetailansicht gibt Ihnen den gleichen Zugriff auf die Testschrittnavigation und die Screenshots, bietet aber zusätzlich spezifische Details zum ausgewählten Gerät, einschließlich CPU- und Arbeitsspeicherauslastung. Aus dieser Ansicht können Sie außerdem auf die Geräteprotokolle und die Stapelüberwachung zugreifen, Artefakte, die beim Untersuchen von Testfehlern besonders vielversprechend sind (siehe Abbildung 4).

Der Gerätedetailbericht.
Abbildung 4 Der Gerätedetailbericht

Bis zu diesem Punkt sind wir dem häufigsten Workflow in Test Cloud gefolgt:

  1. Ausführen des Tests (manuell oder mithilfe von Continuous Integration, kurz „CI“ genannt).
  2. Überprüfen der Ergebnisse.
  3. Abrufen der Debugartefakte.
  4. Beheben der gefundenen Fehler.

Als Nächstes erörtere ich ein paar einfache Überlegungen für Ihre Strategie zum Definieren von Zielgeräten und zum Optimieren Ihres Testworkflows auf Leistung, um die Pipeline stets im Fluss zu halten.

Überlegungen zur Geräteabdeckung

Die Auswahl der Geräte, die von Ihrer Organisation unterstützt werden und auf denen letztlich auch getestet wird, ist nahezu ebenso wichtig wie das eigentliche Testen. Zwar gibt es viele Quellen für zusammengefasste und generalisierte Marktdaten, die Ihre Überlegungen auf diesem Gebiet leiten können, trotzdem stellen die Nutzungsdaten Ihrer eigenen Benutzerbasis die einflussreichste Quelle dar. Die Ausnahme davon stellt naturgemäß eine Anwendung dar, die nur intern an einen Satz bekannter und verwalteter Geräte verteilt wird. Für externe und Endverbraucher-Apps sowie interne Apps, die unter einer BYOD-Richtlinie (Bring-Your-Own-Device) verteilt werden, bilden Nutzungsdaten Ihre beste Quelle.

Viele Tools am Markt können Sie beim Sammeln von Einsichten zu den von Ihrem Publikum verwendeten Geräten unterstützen. Dies ist das Dataset, aus dem Sie Ihre Liste unterstützter Geräte extrapolieren können. Welche Methodik Sie im Einzelnen zum Bestimmen der zu unterstützenden Geräte aus der aggregierten Liste verwenden, liegt bei Ihnen und Ihrer Organisation. In den meisten Fällen ist es nicht sinnvoll, jedes einzelne Gerät, das in Ihren Nutzungsdaten vorkommt, zu unterstützen, da das schnell sperrig und teuer wird. Sie können sich entscheiden, so viele Geräte zu unterstützen, dass Sie damit einen bestimmten Prozentsatz Ihrer Benutzerbasis abdecken. Oder Sie können sich an der Benutzeranzahl orientieren und so viele Geräte unterstützen, dass weniger als 500 Geräte von Benutzern ohne Unterstützung bleiben. Wenn Sie eine E-Commerce-App betreiben, kann es sinnvoll sein, Ihre Nutzungsdaten mit Transaktionsdaten zu verknüpfen, um sicherzustellen, dass die Geräte abgedeckt werden, von denen aus besonders hohe Beträge ausgegeben und besonders häufig Transaktionen vorgenommen werden. Auch hier sollte der spezifische Ansatz, den Sie zum Entwickeln Ihrer Liste unterstützter Geräte verwenden, von den Erfordernissen und Zielen Ihres Geschäfts ausgehen.

Bedenken Sie, dass sich der Markt für mobile Geräte schnell verändert. Das bedeutet, dass Sie Ihre Nutzungsdaten regelmäßig untersuchen müssen, damit Ihre Liste unterstützter Geräte zutreffend und sinnvoll ist. Achten Sie auf Marktsignale, die darauf hinweisen können, dass der Zeitpunkt für eine erneute Überprüfung der Daten gekommen ist, wie etwa das Rollout eines neuen Gerätemodells oder Betriebssystems.

Optimieren Ihrer Testpipeline

Die beste Möglichkeit, den größten Nutzen aus der Testautomatisierung zu ziehen, besteht in frühen und häufigen Tests. Dadurch werden Zeit- und Kostenaufwand für das Beheben von Programmfehlern verringert und eine durchlässige Bereitstellungspipeline gewährleistet. Jedoch kann es in dem Maß, in dem Teams und Vorgänge skalieren, zu Wartezeiten kommen, und die Produktivität der Entwickler kann nachlassen. Sehen wir uns ein paar Verfahren an, mit denen sich die Pipeline durchlässig und die Produktivität hoch halten lässt.

Nicht alle Tests sind gleich In dem Maß, da Projekte im Lauf der Zeit anwachsen, kann die Ausführung von Testsammlungen länger dauern. Es gibt einen Wendepunkt, an dem das Ausführen der Testsammlung nach dem Vornehmen einer einfachen Änderung mühsam und schwerfällig wird, was oftmals zu schlechten Gewohnheiten führt, wie etwa dem Auslassen von Tests. Sie können dem vorbeugen, indem Sie frühzeitig über die kritischen Pfade Ihrer Anwendung nachdenken – also welche Workflows oder Teile der Benutzererfahrung in Ihrer Anwendung unter allen Umständen funktionieren müssen. Im Ausgang von dem früheren E-Commerce-Beispiel kann das bedeuten, dass Benutzer Produkte durchsuchen, sie dem Einkaufswagen hinzufügen und auschecken können müssen. Es ist weniger wichtig, dass die Benutzer ihre Benachrichtigungseinstellungen festlegen können. Wenn diese Struktur etabliert ist, wird die Ausführung von Tests bei jedem Push oder sogar jedem Commit praktisch viel besser durchführbar. Statt für kleine Änderungen die gesamte Testsammlung auszuführen, können Sie nur die Teile ausführen, die Teil des kritischen Pfads sind. Wie Sie diese Grenzziehung im Einzelnen vornehmen, hängt von dem von Ihnen verwendeten Testframework ab.

Die richtigen Geräte zur richtigen Zeit Zwar kann das Testen jedes Pushs auf einen Featurebranch unter Qualitätsgesichtspunkten ideal sein, jedoch wird es für große Teams schnell sehr aufwändig, insbesondere, wenn viele verschiedene Gerätekonfigurationen unterstützt werden. Sie können diesen Mehraufwand hier verringern, indem Sie bei diesen Testläufen eine progressive Strategie auf Ihre Auswahl der Zielgeräte anwenden. Muss ein Build eines nicht zur Produktion gehörenden Zweigs für jedes unterstützte Gerät getestet werden? Die Antwort ist wahrscheinlich: nein. Stattdessen können Sie eine vernünftige Anzahl Geräte auswählen, die einen sinnvollen Kompromiss zwischen effektiven Tests und verkürzten Wartezeiten ermöglicht. Für einen Präproduktionsbuild aus CI bietet eine repräsentative Beprobung der beliebtesten Gerätemodelle und Betriebssystemversionen aus Ihrer Liste unterstützter Geräte ein gültiges Maß an Abdeckung, ohne Ihre Buildzeit über eine Stunde anwachsen zu lassen. Für einen Einzelentwickler, der von einer lokalen Arbeitsstation aus testet, kann ein Test auf ein oder zwei Geräten ausreichend sein.

Dies sind nur einige Beispiele für denkbare Vorgehensweisen beim Konfigurieren Ihres Testworkflows. Im weiteren Sinn liegt der wichtigste Punkt darin, Zeit in die Überprüfung des optimalen Pipelineflusses zu investieren. Selbst wenn Sie diese Frage bereits beantwortet haben, ist es in jedem Fall sinnvoll, regelmäßig zu prüfen und ggf. Anpassungen vorzunehmen – wie bei allem, was Sie tun.

Zusammenfassung

In diesen Artikel haben Sie erfahren, wie einfach die Migration von der Ausführung von Tests auf einem Emulator oder einem einzelnen lokalen Gerät zur Xamarin Test Cloud ist, um die Leistungsfähigkeit von Hunderten von Gerätekonfigurationen zu nutzen. Ferner wurden einige Strategien zum Organisieren Ihrer Testworkflows und zum optimalen Nutzen Ihrer Testressourcen vorgestellt. Wenn Sie Test Cloud noch nicht verwenden, können Sie sich unter bit.ly/2e3YgTy für eine kostenlose Testversion registrieren, um sie noch heute für Ihre Projekte zu verwenden.


Justin Raczak ist leitender Programm-Manager bei Microsoft und führt den Service zur Automatisierung von mobilen Tests. Er ist zwar erst seit Kurzem bei Microsoft, jedoch hat er schon die letzten drei Jahren automatischen Tests und ihrer Rolle in der Fortentwicklung von Continuous Delivery gewidmet. Sie erreichen ihn unter justin.raczak@microsoft.com.

Unser Dank gilt dem folgenden technischen Experten bei Microsoft für die Durchsicht dieses Artikels: Simon Søndergaard
Simon Søndergaard ist Softwareentwickler bei Microsoft.