Bei der Entwicklungstechnologie einer App hat man die Qual der Wahl, wobei jede Entscheidung des Entwicklers auch direkte Auswirkungen auf die Arbeit der Tester hat. Gerade die Automatisierungsmöglichkeiten werden dadurch entweder massiv eingeschränkt oder vergrößert. In der Windows-Phone-App-Welt stehen im Grunde genommen vier Technologien zur Auswahl: JavaScript- bzw. Webtechnologien, C++, Windows Phone Silverlight 8.1 und Windows Phone (WinRT).
Beim ersten Typ gehören Frameworks wie PhoneGap oder Apache Cordova zum Standardrepertoire der Entwickler. Aus Testsichtweise ist man hier mit Visual Studio primär auf Unit Testing beschränkt. Scheut man sich nicht vor anderen Tools, wäre der Ripple Emulator für Chrome eine Alternative. Diese Extension bildet das Verhalten und die Hardware eines mobilen Gerätes im Desktopbrowser nach. Auch beim zweiten und dritten Typ sind die Testmethoden primär Unit Testing und manuelles Testen. Beim vierten Typ hingegen stehen Ihnen alle Testing-Wege offen: neben den Unit und Integrationstests wird auch UI-basiertes Testen unterstützt.
Zu guter Letzt gibt es noch die Universal-Apps, eine Kombination aus zwei plattformspezifischen App-Typen sowie Code-Sharing-Projekten. Als Testmethoden sind hier alle bereits bekannten Testmethoden aus der Windows- und Windows-Phone-Welt möglich: das Unit/Integration und UI Testing. Die besondere Herausforderung hier ist, auch beim Testen möglichst viel Code für beide Plattformen wiederverwenden zu können.
Testinfrastruktur
Microsoft bietet zum Testen und Entwickeln verschiedene Entwickler-Images zur lokalen Installation an, die sich in Betriebssystemversion und Formfaktor unterscheiden. Als Basis für die diversen Windows Phone Images dient Hyper-V – dementsprechend müssen die Entwicklungs- und Test-PCs Hyper-V-fähig sein und mindestens Windows 8 bzw. Windows Server 2012 als Hostsystem mitbringen. Aus diesem Grund ist das Entwickeln in einer Azure VM aktuell (noch) nicht möglich. Das virtuelle Phone Image bringt viele aus der Virtualisierungswelt bekannte Funktionalitäten mit, z. B. Snapshots. Dazu kommen unter anderem die Emulation von Mobile-Hardware wie GPS, ein Beschleunigungssensor, eine Kamera, ein Netzwerk, eine SD-Karte oder ein Lichtsensor. Die CPU-Architektur ARM wird allerdings nicht direkt nachgebildet. Alle Tests werden aufgrund von Hyper-V nur in einer x86-basierenden CPU ausgeführt. Vorteilhaft ist an diesem Konzept, dass der Emulator im Gegensatz zu Windows-Mobile-Zeiten relativ schnell ist. Aufgrund dieser Besonderheit in der CPU-Architektur sind die Images aber nur für funktionale Tests geeignet. Muss die App bestimmte Performancekennzahlen einhalten, ist ein Test auf unterschiedlicher Hardware mit verschiedenen Leistungsdaten zwingend als weitere Teststufe notwendig.
Bei den Testframeworks hat Microsoft an die Unterstützung von echter Hardware gedacht. Sowohl Unit als auch UI-Tests lassen sich direkt auf physischen Geräten ausführen. Der manuelle Testaufwand kann also auch bei sehr vielen verschiedenen Geräten zu einem Großteil automatisiert werden. Um ein physisches Gerät mit eigenen Apps und Tests zu versehen, ist als erster Schritt dessen Freischaltung als Entwicklergerät notwendig. Danach können Sie beliebige Apps auf das Gerät ausrollen und dort sogar direkt debuggen. Voraussetzung zur Freischaltung ist eine Entwicklerregistrierung – für MSDN-Abonnenten ist diese kostenlos, andernfalls fällt eine Jahresgebühr in Höhe von 14 Euro an. Für die virtuellen Entwickler-Images ist eine Registrierung hingegen nicht notwendig. Automatisierte Tests können über Visual Studio im Emulator oder die Kommandozeile (vstest.console.exe) auf einem physischen Gerät ausgeführt werden. VSTest.Console ist die Kommandozeilenversion des neuen Visual-Studio-Testexplorers. Als Konsequenz werden auch fremde Testframeworks bei entsprechend installierten und unterstützten Testadaptern unterstützt. Um Tests auf einem physischen Gerät auszuführen, ist die Angabe einer Runsettings-Datei notwendig, die die Laufzeitumgebung des Testrunners konfiguriert:
Device
Abb. 1 zeigt die Ausführung über die Kommandozeile mit der Generierung von importfähigen Visual-Studio-Testergebnissen (TRX). Damit die Ausführung auf dem Gerät funktioniert, muss dieses per USB mit dem Test-/Entwickler-PC verbunden sein.
Testmanagement
Ein Testprozess, egal, ob wir über klassische oder mobile Anwendungen reden, ist laut ISTQB (International Software Testing Qualifications Board) in fünf Prozessschritte eingeteilt: Planung und Steuerung, Analyse und Design, Realisierung und Durchführung, Auswertung und Bericht sowie Abschluss. In der Visual-Studio-Welt lassen sich alle Phasen durch TFS, VS, MTM und Office (Word, Excel, Project) abdecken. Dabei ist der MTM im Bereich Testmanagement das primäre Werkzeug. Auch vor dem Testen von Mobilanwendungen sollte ein Testplan mit allen zu berücksichtigenden Test- bzw. Anwendungsfällen erstellt, geplant und priorisiert werden. Nur wenn eine entsprechende Planung existiert, können die richtigen Bereiche getestet und Ressourcen geplant werden. Die Phase der Realisierung und Durchführung findet je nach Testmethode in zwei verschiedenen Werkzeugen statt. Die manuelle Testausführung erfolgt im MTM, der dem Tester die einzelnen Testschritte und das erwartete Ergebnis anzeigt. Wird dieses nicht erreicht, können Bugs direkt im TFS erfasst werden. Wird der MTM in Kombination mit Windows Phone eingesetzt, ist die Erfassung von Rich Bugs beim Einsatz von Diagnoseadaptern minimal eingeschränkt: Aufgrund des fehlenden direkten Zugriffs funktionieren die Adapter für Event Logs, Action Recordings, IntelliTrace und Test Impact nicht. Sinnvoll einsetzen lassen sich hingegen die Diagnoseadapter Video und Voice Recording und Screenshots. Sie ermöglichen, den aktuellen Bildschirminhalt in Videoform aufzuzeichnen. Die Aufzeichnung einer Anwendung im Emulator ist kein Problem, weil dieser als Windows-Anwendung läuft. Möchten Sie hingegen eine Videoaufzeichnung eines Hardwaredevices anfertigen, können Sie den Bildschirminhalt Ihres Windows Phone über Software Beam auf Ihren Desktop projizieren, sodass er für den MTM sichtbar wird. Mit dieser Methode können Sie Fehler reproduzierbar im TFS in Bug Work Items ablegen.
Neben der Videoaufzeichnung sind für das manuelle Testen noch die Windows Phone Developer Power Tools interessant. Dieses Werkzeug macht Performancewerte aus dem Emulator und vom Gerät auslese- und auswertbar. Zu den Kennzahlen zählen z. B. Speicher, CPU und Grafikkartenaktivität.
[ header = Seite 2: UI Testing ]
UI Testing
Das Testen von Oberflächen kann über das Framework Coded UI realisiert werden. Es unterstützt beispielsweise WPF, WinForms, Windows-Store- und Webanwendungen und seit Visual Studio 2013 Update 2 auch Windows-Phone-Apps. Ähnlich wie bei Windows-Store-Apps erfolgt auch hier eine Limitierung auf XAML-basierte Anwendungen. Die anderen App-Typen wie Silverlight-, HTML- und C++-Apps werden aktuell nicht in Coded-UI-Tests unterstützt. Als Alternative bleibt hier nur der Weg über Unit/Integration Tests auf Codeebene sowie manuelles UI Testing.
Bevor man mit dem Schreiben von UI-Tests beginnt, sollte die Anwendung auf ihre Tauglichkeit für solche Tests untersucht werden. Coded UI funktioniert für XAML-Apps auch ohne große Optimierungen – die Erfahrung hat allerdings gezeigt, dass Unzufriedenheit mit Coded UI in den meisten Fällen auf fehlende Optimierungen zurückzuführen ist. Bei Phone-Apps sind, genauso wie bei den Store- und WPF-Apps, die AutomationProperties AutomationId und Name aus der Accessibility-Schnittstelle UIA von großem Interesse. Über diese Properties können Controls auf der Oberfläche eindeutig identifiziert werden. Setzt der Entwickler diese Eigenschaften nicht, führen alle Controls automatisch eine Fallback-Strategie aus: der jeweils angezeigte Control-Text wird automatisch zu AutomationId bzw. Name. Problematisch wird dies, wenn z. B. DisplayTexts lokalisiert sind oder sich anderweitig dynamisch setzen. Das bewusste Zuweisen der AutomationProperties kann entweder mittels Blend oder manuell im XAML-Markup-Code geschehen. Der Vorteil einer automatischen Zuweisung per Blend besteht darin, dass alle Controls mit wenig Aufwand zugewiesen werden können. Die Namen sind allerdings nicht wirklich sprechend. Besser für eine langfristige Wartbarkeit ist die manuelle Zuweisung, denn manuell zugewiesene Namen sind sprechender, und der darauf aufbauende Code ist zwecks Wartbarkeit und Verständnis wesentlich besser lesbar. Der folgende Code zeigt ein Beispiel aus der 7Pass-App für optimierte Controls:
// Datei: EntryFieldValue.XAML // TextBox mit UIA Properties ...// ToggleSwitch mit UIA Properties ...
Nachdem unsere App mit AutomationProperties vorbereitet ist, geht es an das Schreiben der Tests. Visual Studio bietet standardmäßig als Erstes die Erstellung von UIMaps mit dem Coded UI Test Builder an. Eine UIMap ist eine generierte .NET-Bibliothek mit Klassen zum Ansteuern von UI-Controls und -Methoden zum Ausführen und Prüfen.
Eine bessere Möglichkeit zum Aufbau von UI-Test ist, den Code für das UI-Test-Framework manuell zu schreiben. Dieser selbstgeschriebene Code hat den Vorteil, dass die Redundanz des Codegenerators vermieden und die Wartbarkeit durch Wiederverwendbarkeit erhöht wird. Gleiche Logik und Einstellungen können einfach in zentralen Klassen ausgelagert werden. Ändert sich die UI-Struktur der App, müssen nur wenige Stellen angepasst werden. Den Beginn markiert die Klasse BaseUIObject, in der wir allgemeingültige, übergreifende Logik ablegen. Im Beispiel unserer App „7Pass“ wären dies z. B. generische Methoden zum Ansteuern der Textboxen, das Auslösen der Hardwarebuttons (Suche-, Zurück-, Windows-Button) oder das Umschalten der Hub-Sichten (Listing 1). Die Klasse BaseUIObject wird im nächsten Schritt von den spezifischen UI-Objekten für die einzelnen Szenarien, Views oder Fenster abgeleitet. Die UIObject-Strategie hängt letztendlich von der jeweiligen Anwendung ab. Am Beispiel der 7Pass-Anwendung ergeben sich exemplarisch CommonUI, PasswordEntryUI, PasswordEntryDetailsViewUI, PasswordEntryAttachmentsViewUI, PasswordEntryFieldsViewUI und PasswordEntryNotesViewUI.
public class BaseUIObject { // Eigenschaft um zentral eine Referenz auf das App Fenster zu halten public XamlWindow AppWindow { get; set; } // Generische Methoden zum Finden von Controls auf Basis des UIA Automation Namen public T FindXamlControlByName(UITestControl rootControl, string name, bool searchByFrameworkId = true) where T : XamlControl, new() { var xamlControl = new T { Container = rootControl }; xamlControl.SearchProperties.Add(XamlControl.PropertyNames.Name, name); if (searchByFrameworkId) xamlControl.SearchProperties.Add(XamlControl.PropertyNames.FrameworkId, "UIX"); return xamlControl; } // Generische Methoden zum Finden von Controls auf Basis des UIA Automation ID public T FindXamlControlById (XamlControl rootControl, string automationId, bool searchByFrameworkId = true) where T : XamlControl, new() { // ... } // Generische Methoden zum Finden von Controls auf Basis der Framework ID public T FindXamlControlByFrameworkId (XamlControl rootControl, string frameworkId) where T : XamlControl, new() { // ... } // Zurück Hardware Button auslösen public void PushGoBackButton() { Device.HardwareButton.Back(); } // Start Hardware Button auslösen public void PushStartButton() { Device.HardwareButton.Start(); } ... }
In der CommonUI-Klasse sind anwendungsspezifische übergreifende Aktionen ablegt, z. B. StartApp, StopApp, OpenPasswordFile, AddPasswordFile, SelectFolder und SelectEntry (Listing 2). Als Nächstes steht die Implementierung der spezifischen UI-Objekte für die diversen Hub-Sichten an. Ein Passworteintrag in 7Pass enthält vier Hub-Sichten. Aus diesem Grund legen wir noch eine UIObject-Klasse (PasswordEntryUI) für einen Passworteintrag mit Navigationslogik für das Umschalten der Sichten an. In Form von Methoden sind dies GoToDetailsView, GoToNotesView, GoToAttachmentsView und GoToFieldsView (Listing 3). Interessant dabei ist der Einsatz von Gesten zum Umschalten der Views, was hier per Swipe-Geste von links nach rechts erledigt wird. In Windows-Store- und Windows-Phone-Apps können diverse Gesten per Gesture-Klasse gesteuert werden.
// App starten XamlWindow myAppWindow = XamlWindow.Launch("My App GUID"); public class CommonUI : BaseUIObject { public XamlControl Window { get; set; } // Starten einer App auf Basis der AutomationID // AutomationID wurde mit dem CodedUI TestBuilder ermittelt public void StartApp() { AppWindow = XamlWindow.Launch("{9784297B-2DBB-49A2-8247-19A3756BBD20}:App:9784297b-2dbb-49a2-8247-19a3756bbd20_p01659jmcbgp6!App"); } // Schliessen der gestarteten App public void CloseApp() { if (null != AppWindow) AppWindow.Close(); } // Eine Passwort Datei in 7Pass hinzufügen // Dialog ist mehrstufig public void AddPasswordFile() { // App Fenster finden Window = FindXamlControlByFrameworkId(XamlWindow.Desktop, "UIX"); // Add Button auslösen var addButton = FindXamlControlByName (Window, "add"); // Windows Phone kennt keine Maus Aktion, sondern nur Gesten // Tap ist die Windows Phone Version eines Mausklicks Gesture.Tap(addButton); // Dialog schaltet um -> Phone auswählen var selectStorage = FindXamlControlByName (Window, "Phone"); Gesture.Tap(selectStorage); // Dialog schaltet um -> SD Karte als Ordner auswählen var selectFolder = FindXamlControlById (Window, "KnownFoldersList", false); var selectSDCard = FindInListByLabelText(selectFolder, "sd card"); Gesture.Tap(selectSDCard); // Dialog schaltet um -> Datei NewDatabase.kdbx auswählen // Mehrstufiges suchen notwendig, weil 7Pass noch nicht auf jeder Ebene AutomationId eingeführt hat // Suche nach ListItem Control auf Basis des Label Textes var folderContentsListView = FindXamlControlById (Window, "PART_FolderContentsListView", false); var folderViewContentGroup = FindXamlControlByName (folderContentsListView, "Microsoft.Phone.FileManager.ViewModels.FolderViewContentGroup", false); foreach (var fileGroupChildControl in folderViewContentGroup.FindMatchingControls()) { var fileEntry = FindInListByLabelText(fileGroupChildControl, "NewDatabase.kdbx"); Gesture.Tap(fileEntry); } } // Öffnen einer hinzugefügten Passwort-Datei public void OpenPasswordFile() { // App-Fenster finden Window = FindXamlControlByFrameworkId (XamlWindow.Desktop, "UIX"); // Liste mit Keepass-Dateien finden var databasesList = FindXamlControlById (Window, "Databases", false); // Gewünschte Datei auswählen var selectDB = FindInListByLabelText(databasesList, "NewDatabase"); Gesture.Tap(selectDB); // Dialog schaltet um -> Passwort eingeben var passwordBox = FindXamlControlById (Window, "Password", false); passwordBox.Text = "test"; // Eingabe durch Drücken von Öffnen bestätigen var openButton = FindXamlControlByName (Window, "open"); Gesture.Tap(openButton); } ... }
public class PasswortEntryUI : BaseUIObject { public XamlControl Window { get; set; } public void GoToDetailsView() { // App-Fenster suchen Window = FindXamlControlByName(XamlWindow.Desktop, "7Pass Remake", false); // Passwortdatei Hub-View suchen var newDatabaseHub = FindXamlControlByName (Window, "NewDatabase", false); // Details-Label suchen var detailsLabel = FindXamlControlByName (newDatabaseHub, "Details", false); // IsVisible ist eine eigene Extension-Methode // Auf Basis der Koordinaten wird entschieden, ob die Hub-View im sichtbaren Bereich ist if (!detailsLabel.IsVisible()) { // Die maximale Anzahl an Swipes ist abhängig von der Anzahl an Hub Views for (int i = 0; i < newDatabaseHub.GetChildren().Count; i++) { // Auslösen der Swipe-Geste in die linke Richtung mit der Länge 200px auf dem ersten Element des App-Fensters Gesture.Swipe(Window.GetChildren()[0], UITestGestureDirection.Left, 200); } } ... }
Nun steht die Umsetzung der Views als UI-Objekte an. Am Beispiel der PasswordEntryDetailsViewUI wären Methoden wie EnterUserName, CheckUserName, EnterPasswort, ChechPasswort, OpenBrowser und IsDetailsViewOpen sinnvoll. Ein Beispiel (CheckUserName) für eine automatische Prüfung mit Asserts finden Sie in Listing 4. Die UI-Tests können dann über den Visual-Studio-Testexplorer auf einem Emulator-Image oder einem Gerät zum Einsatz kommen.
public class PasswordEntryDetailsViewUI : BaseUIObject { public XamlControl Window { get; set; } // Prüfe, ob Michael321 als Nutzername eingegeben wurde public bool CheckUserName() { // App-Fenster suchen Window = FindXamlControlByName(XamlWindow.Desktop, "7Pass Remake", false); // Passwortdatei Hub-View suchen var newDatabaseHub = FindXamlControlByName (Window, "NewDatabase", false); // Suche Username Textbox var userNameEditBox = FindXamlControlById (newDatabaseHub, "UserName", false); // Prüfe, ob Nutzername Michael321 in der Textbox vorkommt Assert.AreEqual("Michael321", userNameEditBox.Text); return true; } ... }
[ header = Seite 3: Unit/Integration Testing ]
Unit/Integration Testing
Der UI-Test oder auch Systemtest ist die höchste Ebene in der Testpyramide. Die unterste Schicht stellen die Unit Tests dar, und dazwischen liegen die Integrationstests. Anders als beim UI-Test kennen wir hier die Applikationsimplementierung und führen also einen White-Box-Test durch. Entscheidend sind in der modernen Applikationsentwicklung neben einem ansprechenden GUI auch der App-Unterbau und eine gute Softwarearchitektur. Da diese mit der Entwicklung mitwächst, lautet das oberste Ziel, keinen Wildwuchs zu erhalten und den bestehenden Code mittels Refactoring auf die neuen Anforderungen hin anzupassen. Somit liegt es auf der Hand, auch im Mobile-Bereich einen Test-driven-Development-Ansatz (TDD) zu fahren und getreu dem Motto „Red Green Refactor“ die Arbeit voranzutreiben.
Egal, ob die App nur das Frontend für einen Backend-Service darstellt oder auch die Businesslogik sowie Persistenzschicht enthält, die Anforderungen an Schichtenarchitektur, Entkopplung und Modularisierung sind dieselben. Die Vorgehensweise und Patterns für qualitativ hochwertigen und einfach testbaren Code unterscheiden sich indes kaum von denen in der Windows-Applikationsentwicklung. Als Grundlage für den gesamten Code dient das Dependency-Injection-Pattern. Zu den Anfängen der Windows Runtime kaum denkbar, sind mittlerweile einige Dependency-Injection-Container-Implementationen für WinRT vorhanden, beispielsweise für Unity. Die Abhängigkeiten einer Klasse werden in Form von Interfaces definiert. Abb. 2 zeigt auf der linken Seite die Implementation des View Models, das die Abhängigkeiten mittels Constructor Injection definiert. Zur Laufzeit werden dann die konkreten Implementierungen vom Dependency-Injection-Container geliefert. Für Unit und Integrationstests eignen sich die Interfacedefinitionen der Abhängigkeiten ideal zum einfachen Isolieren der internen und externen Abhängigkeiten durch Stubs oder Mocks. Der Unit Test auf der rechten Seite zeigt die Instanziierung der Mocks sowie die eigentlichen Unit Tests.
In der View-Logik gelten dieselben Prinzipien: Sie lässt sich einfach und effizient testen, wenn wir keine harten Referenzen zur Visualisierung haben. Anstatt die View-Logik in der Code-Behind-Datei zu implementieren, verwenden wir das MVVM-Pattern. Model View ViewModel (MVVM) entkoppelt hierbei die einzelnen Komponenten und verbindet sie über die Binding-Funktionalität von XAML. Somit können wir das View Model, das aus dem Laden und Validieren der Daten sowie der Implementation der Aktionen besteht, relativ einfach mittels eines Unit Tests überprüfen und müssen hierzu nicht einmal das UI hochfahren. Zur Implementierung des MVVM-Patterns empfehlen wir die Verwendung eines Frameworks. Die bekannte Bibliothek Prism steht neuerdings auch für XAML-basierte Windows-Runtime-Apps zur Verfügung. Als Alternative ist Caliburn.Micro zu erwähnen, das auch von unserer Demo-App 7Pass verwendet wird.
Um ein neues Unit-Test-Projekt zu erstellen, wird der entsprechende Projekttyp für die Windows-Phone-App ausgewählt. Die Vorlage erstellt ein Unit-Test-Projekt basierend auf MSTest. Bei xUnit wird derselbe Projekttyp verwendet, die Referenz auf das MSTest-Framework jedoch entfernt und das NuGet Packet „xunit“ mit Version 2.0 hinzugeführt (derzeit nur als Pre-Release verfügbar). Die gewählte Architektur sowie die definierten Module haben natürlich auch Einfluss auf die physikalische Codeverwaltung respektive Generierung der Assemblies. Für Windows-Phone-Apps können ebenfalls DLLs in Form von Class Libraries erzeugt werden. Vielmals ist aber gerade der Logikcode prädestiniert dazu, ausgelagert und in mehreren Apps übergreifend verwendet zu werden. Hier kann eine so genannte Portable Library zum Einsatz kommen. Abhängig von der ausgewählten Zielplattform ändert sich das zur Verfügung stehende API (Abb. 3).
Wird dieselbe Applikation als Windows-Store-App und Windows-Phone-App benötigt, kann der seit Visual Studio 2013 Update 2 zur Verfügung stehende Projekttyp „Universal App“ verwendet werden. Hierbei werden zwei plattformspezifische Applikationen erstellt und gemeinsamer Code in ein so genanntes Shared Code Project (*.shproj) ausgelagert. Was sich zunächst toll anhört, ist jedoch ein Problem für das Unit Testing. Ein Unit-Test-Projekt muss für die Windows- und Windows-Phone-App separat erstellt werden. Es ist nicht möglich, den geteilten Code direkt zu testen. Da wir selbstverständlich nur testbaren Code in unserem Projekt haben möchten, kommen wir also nicht drumherum, zwei Testprojekte zu erzeugen. Einen Shared Unit Test gibt es (noch) nicht. Auch bei Universal-Apps können Portable Libraries referenziert werden, die wiederum getestet werden können. Wenn nicht der vollständige zu testende Code in ein separates Assembly ausgelagert werden kann, wäre es trotzdem schön, analog zur Universal-App ein Shared Code Project für den Unit-Test-Code zu erhalten. Unsere Demo-App zeigt dies beispielhaft auf.
Abb. 4 zeigt die Projektstruktur unserer Beispiel-Applikation 7Pass. Der Großteil des Applikationscodes ist für beide App-Projekte im Shared Code Project „SevenPass.Shared“ implementiert. Wie erwähnt, müssen die beiden Apps jeweils separat mit einem Unit-Test-Projekt getestet werden. Um den Unit-Test-Code für die gemeinsam genutzten Klassen nicht zu duplizieren, wurde hierbei ein Shared Code Project verwendet. Dies ist im Standard noch nicht vorgesehen, kann aber entweder manuell in den Projektdateien nachgepflegt werden. Alternativ kann die Visual Studio Extension „Shared Project Reference Manager“ zum Einsatz kommen. Mit ihr lassen sich Shared Code Projects über die Projekttemplates erstellen und von anderen Projekten referenzieren. In unserem Beispielprojekt referenzieren jeweils die Projekte 1 und 2 das Shared Code Project 3, analog gilt das auch für Applikations- und Testprojekte.
Fazit
Damit die Benutzung von Windows-Phone-Apps für den Kunden zum erfreulichen Erlebnis wird, ist die Qualitätssicherung eine sehr wichtige Komponente. Apps für Windows Phone lassen sich mittels verschiedener Frameworks implementieren, jedoch steht das komplette QA-Tooling inklusive UI-Automatisierung nur für XAML-basierte Windows-Phone-Apps zur Verfügung. Für die anderen App-Typen sind zumindest Unit-Test-Frameworks vorhanden. Mittels Automatisierung kann die Arbeit der Tester interessanter gestaltet werden, da die Routinetestfälle von der Automatisierung übernommen werden und sie primär neue oder sehr komplexe Anforderungen testen. In diesem Artikel haben wir gezeigt, dass sich auch im App-Bereich eine gute Architektur für stabilen und gut testbaren Code auszahlt. Viele WPF-Entwickler finden mittlerweile Portierungen ihrer verwendeten MVVM und Composite-Application-Frameworks für WinRT und können somit ihr Know-how einfach in die App-Welt übertragen.