28.01.2020

Delivery und Testing mit Microsoft Azure DevOps

Im letzten Artikel haben wir Ihnen Einblicke in die Umsetzungsplanung sowie das Reporting von Microsoft Azure DevOps gegeben. In diesem Artikel soll es nun um die (kontinuierliche) Auslieferung der umgesetzten Softwareinkremente gehen als auch das anschließende Testen.

Nachdem in unserem letzten Artikel zu Microsoft Azure DevOps das Refinement der Anforderungen sowie die Sprintdurchführung und Kollaboration im Vordergrund standen, widmen wir uns jetzt der kontinuierlichen Auslieferung neu entwickelter Inkremente sowie dem Testen. Dabei werden wir auch auf das Konzept der Continuous Integration und Continuous Delivery eingehen.

Continuous Integration und Continuous Delivery (CI/CD)

Die kontinuierliche Integration oder Continuous Integration beschreibt eine Entwicklungspraktik, die verlangt, dass der entwickelte Code regelmäßig (bspw. täglich) in einem gemeinsamen Repository abgespeichert wird – das relevante Modul in Azure DevOps nennt sich Repos. Ein Repository und Versions-Kontrollsystem kann sicherstellen, dass mehrere Entwickler Code einchecken, Artefakte über eine Build Pipeline gebaut (Build) und automatisch getestet werden können. Hierbei handelt es sich üblicherweise um automatisierte Unit- und Integrationstests.

In unserem Szenario gibt es einen DEV Branch für den jeweils aktuellen Entwicklungsstand und Feature Branches, die von 1-n Entwicklern für die Arbeit an einem bestimmten Feature genutzt werden. Bei jedem Push-Request in diesen Branch (ein Entwickler checkt von seiner lokalen Entwicklungsumgebung die Code-Änderungen am Feature in die Feature Branch ein), lässt sich bspw. ein Code-Review als Schritt einfügen oder auch automatische Unit- und Integrationstests festlegen. Dadurch können frühzeitig mögliche Fehler entdeckt und direkt korrigiert werden, noch bevor ein zusammenhängendes Feature für manuelle Tests auf einer Testumgebung ausgerollt wird.

Die kontinuierliche Auslieferung oder Continuous Delivery beschreibt eine Methode, die darauf ausgerichtet ist, dass Software während ihres gesamten Lebenszykluses in einem veröffentlichungsfähigen Zustand ist. Somit verfügt man stets über eine schnelle und automatisierte Rückmeldung bzgl. der Produktionsbereitschaft eines Systems. Dies reduziert nicht nur Kosten, sondern auch Zeit und das Risiko beim Ausliefern inkrementeller Änderungen.

Wie aber unterstützt nun Azure DevOps diese Methoden? In Azure DevOps gibt es das Modul „Pipelines“. Mithilfe dieses Moduls lässt sich ein genaues Umgebungsszenario aufbauen und festlegen - in unserem Projektbeispiel haben wir dabei die Umgebungen QA, UAT und PROD aufgebaut. Wenn der zuvor erzeugte Build im DEV Branch (aus den Feature Branches heraus) erfolgreich war, kann ein Pull-Request in den Master Branch durchgeführt werden, sodass ein Build erzeugt wird, welches innerhalb eines Releases auf unsere Umgebungen ausgerollt werden kann (nachfolgend links zu sehen):

Nachdem der Build fehlerfrei war, kann dieser automatisiert auf beliebigen Umgebungen eingespielt werden. Dabei können auch Zwischen-Gates eingebaut werden, um bspw. automatisiert oder auch manuell eine Validierung durchzuführen, bevor es auf die nächste Umgebung ausgerollt wird. Die innerhalb eines Deployments stattfindenden Schritte können ganz einfach in Azure DevOps konfiguriert und parametrisiert werden:

Anschließend kann in einer Release-Übersicht der jeweilige Deployment-Status angezeigt werden:

Zusammengefasst wird somit das Ziel kleinerer und häufigerer Releases und deren Konsistenz und Geschwindigkeit durch einen hohen Grad an Automation erreicht.

Integriertes Testen in Azure DevOps

Nachdem eine neue Version auf der QA-Umgebung bereitgestellt wurde, geht es ans Testen der neuen Funktionalitäten. Bisher fand innerhalb des Builds lediglich ein automatisierter Unit- und Integrationstest statt, der die technische Fehlerfreiheit bezogen auf eine Einheit bzw. die Integration von Modulen untereinander sicherstellte. Im Rahmen von DevOps spricht man auch vom kontinuierlichen Testen, welches den Prozess des Ausführens von automatischen Tests als Teil der Deployment-Pipeline vorsieht.

Neben den automatisierten Tests ist auch das manuelle Testen der Fachlichkeit von Funktionen und Features häufig notwendig. Das gilt z.B. wenn die Automatisierung von Testfällen hohe Aufwände verursacht. In diesen Fällen ist ein strukturiertes Testmanagement hilfreich. Das Testmanagement erstreckt sich als begleitende Maßnahme über den gesamten Testprozess. Es beinhaltet die Planung, Überwachung und Kontrolle der Aktivitäten aller Testschritte. Den Überblick über alle Aktivitäten, Daten und Status zu behalten ist die Kunst des guten Testmanagements. Daher wird das Testmanagement in der Praxis idealerweise immer toolunterstützt betrieben, da nur dadurch gewährleistet wird, dass die Möglichkeit eines vollständigen Informationsflusses zwischen allen Beteiligten im Projekt gegeben ist. 

Im Allgemeinen folgt das Testen den folgenden Schritten:

  1. Nach dem Sprint Planning übernimmt das Team Anforderungen/User Stories in das Sprintbacklog.
  2. Ein Entwickler zieht (pulled) ein Requirement / User Story / Bug.
  3. Er bespricht die Details mit dem verantwortlichen Tester und / oder beschreibt Details im Work Item.
  4. Der Tester erstellt basierend auf dem Work Item und den Details die Test Cases zur jeweiligen Anforderung (Test-driven Development).
  5. Der Entwickler implementiert die Anforderung / den Bug Fix und testet kurz die umgesetzte Funktionalität (auch in Absprache mit dem Tester, wenn nötig, bzw. auf Basis der erstellten Test Cases).
  6. Der Tester beginnt mit seinem Test der Anforderung. Im Fehlerfall wird ein Bug eingestellt und dem Entwickler zugewiesen. Im Einzelfall können Details auch mit dem Entwickler durchge-sprochen werden.
  7. Durch Regressions- bzw. Fehlernachtests wird die Behebung validiert und der Status des Bugs auf Done gesetzt.
  8. Sind alle Test Cases einer Anforderung erfolgreich durchlaufen, erfolgt die Abnahme der Anforderung durch den Owner.
  9. Dieser setzt dann nach erfolgreicher Abnahme die Anforderung auf Closed.

Der Statusverlauf eines Bugs von der Identifizierung bis zur Behebung lässt sich in Azure DevOps wie folgt abbilden:

Natürlich bietet Azure DevOps auch die Möglichkeit des Trackings im Verlauf der Testplanung und -durchführung. Hierfür können wieder die bereits in einem früheren Artikel vorgestellten Dashboards verwendet werden.

Mit dem Modul Test Plans unterstützt Azure DevOps alle Phasen des Testmanagements. Tests werden dabei in sogenannte Test Suites, Test Cases und Test Steps unterteilt.

Test Suites sind dafür vorgesehen, Test Cases in separate Testszenarien zu gruppieren, um einfach erkennen zu können, welche Testszenarien bereits erfolgreich durchlaufen wurden. Test Cases werden genutzt, um individuelle Teile des App- / Funktions-Deployments auf korrekte Ausführung, Fehlerfreiheit und das Erfüllen der Geschäftsanforderungen hin zu validieren. Um dies zu prüfen, werden innerhalb eines Test Cases die Test Steps ausgeführt und entweder als erfolgreich oder fehlerhaft (Bug) markiert. Der Fehler wird entsprechend erläutert, so dass er im Nachgang durch einen Entwickler nachvollzogen werden kann.

Fazit

Azure DevOps ist ein reifes Werkzeug, dass moderne Praktiken der kontinuierlichen Integration und Auslieferung (CI/CD) von Liefergegenständen unterstützt. Ergänzt um das Testmanagement bietet Azure DevOps viele hilfreiche Features für die Qualitätssicherung und die Verwaltung von Testfällen sowie der Verfolgung von Bugs und Bug Fixes.

In unserem nächsten Beitrag werden wir uns die Themenblöcke Sprint Review und Retrospektive genauer ansehen und wie auch hier Azure DevOps eine integrierte Lösung bietet.