Zufallsgenerierte Tests unter Verwendung einer simulierten Umgebung
Die Erwartungen der Kunden an bessere digitale Erlebnisse steigen. Allerdings kann selbst die kleinste Codeänderung vier bis sechs Wochen in Anspruch nehmen, was unweigerlich zu einer Verzögerung der gesamten Produktion führt. Wie geht man mit der Situation um, wenn jeder Qualität ohne Beeinträchtigung der Liefergeschwindigkeit verlangt, und wie bleibt man der Konkurrenz immer einen Schritt voraus?
Geschwindigkeit und Qualität sind gleichermaßen wichtig, daher sind Automatisierung beim Testen und kontinuierliche Integration nicht länger nur eine Option, sondern eine Notwendigkeit. [1]
Für große Automatisierungsprojekte ist dies möglicherweise nicht ausreichend. Interaktionen mit der Hardware und sogar zwischen Softwaremodulen führen zu einer extrem hohen Komplexität und einer großen Bandbreite möglicher Fehlermodi, die nicht vorhersehbar sind. Daher könnte eine simulierte stichprobenartige Testumgebung die Lösung sein, um diese Probleme zu überwinden.
- Übersicht über häufig verwendete QS-Maßnahmen
- Einführen von Randomisierungen in die Testumgebung
- Zwischenfazit
- Azure zur Unterstützung der Simulation von zufallsgenerierten Tests verwenden
- 4.1. Eine virtuelle Maschine als Basis erstellen
- 4.2. Ihre eigene Image-Datenbank anlegen
- 4.3. Hinzufügen eines Images einer virtuellen Maschine zu Ihrer Image-Datenbank
- 4.4. Erstellen einer virtuellen Maschine aus einem Image in der Galerie
- 4.5. Ausführen der virtuellen Maschine und Starten der Simulation
- 4.6. Verwendung von Skripten zur Optimierung der Image-Erstellung
- 4.7. Fazit
1. Übersicht über häufig verwendete QS-Maßnahmen
1.1. Automatisiertes Testen
Automatisierte Tests beruhen auf der Ausführung mehrerer vordefinierter Szenarien, wobei jedes Mal Teile der Codebasis geändert werden und immer die gleichen Ergebnisse erzielt werden. Dies bedeutet, dass bei einer Änderung der Codebasis alle Komponenten wie erwartet funktionieren.
Das automatisierte Testen umfasst folgende Komponenten [2]:
- Die Verwendung von Skripten zur Steuerung von Tests. Die Tests werden parallel zur Entwicklung vorbereitet, und es wird davon ausgegangen, dass alle möglichen Szenarien im Voraus bedacht werden.
- Hardware zur Unterstützung der Skripte. Die Skripte laufen dann entweder automatisch (in einem bestimmten Intervall oder ausgelöst durch ein Ereignis wie z. B. ein Commit in der Versionsverwaltung) oder manuell (meist nach Fertigstellung eines Features). In jedem Fall müssen sie auf anderen Geräten laufen als auf jenen, die für die Entwicklung verwendet werden, damit der Entwickler weiterarbeiten kann.
- Die Verwendung anderer Skripte zur Aufzeichnung der Ergebnisse oder zumindest eine Zusammenfassung der gelaufenen Tests und ihrer Ergebnisse (erfolgreich oder fehlgeschlagen).
- Eine Theorie oder Philosophie des Testens. Dies erfordert ein Vorausdenken aller möglichen Wechselwirkungen aller Module.
- Die Fähigkeit, Fehler zu erkennen. Überlegen, was passieren soll und was nicht.
Auch wenn automatisiertes Testen also in einigen Situationen geeignet ist (z. B. Testen aller regelmäßig verwendeten Szenarien unter optimalen Bedingungen oder nahe daran), reicht es bei Projekten mit einer großen Anzahl interagierender Module möglicherweise nicht aus. Auf der einen Seite wäre es sehr schwierig, alle möglichen Szenarien und alle Wechselwirkungen zu bestimmten Zeiten vorherzusagen; auf der anderen Seite wäre der Aufwand an Zeit und Hardware, um all diese möglichen Szenarien auszuführen, erheblich.
1.2. Simulation
Die Simulation beruht darauf, die Hardware als Software zu simulieren, um festzustellen, wie sich die Software verhalten würde, wenn sie auf der Hardware installiert wäre.
1.2.1. Anwendung [2]
- die Generierung von Anforderungen erleichtern;
- unbekannte Wechselwirkungen und Details des Designs aufdecken;
- die Entwicklungskosten reduzieren, indem weniger tatsächliche Teile benötigt werden.
1.2.2. Zielsetzungen der Simulation [2]
- Schnelle Bewertung verschiedener Designkonzepte, ohne Materialeinsatz
- Demonstration der Systemintegration (Peer Reviews und Kundenfeedback)
- Verfeinerung von Designkonzepten durch Prognose der Auswirkungen von Leistungsparametern auf das Systemverhalten
- Überprüfung des korrekten Verhaltens des simulierten Objekts über einen weiten Bereich von Nenn- und Fehlerszenarien
- Identifizieren von Schlüsselvariablen, die auf das System einwirken, und Erkennen der Auswirkungen auf das System, insbesondere im Hinblick auf mögliche Wechselwirkungen
- Folgen für die Reliability o Theoretische Simulationsergebnisse als Referenz für die praktische Überprüfung.
- Folgen für die Reliability o Theoretische Simulationsergebnisse als Referenz für die praktische Überprüfung.
1.2.3. Simulationsaktivitäten [2]
Um mit der Entwicklung einer Simulation zu beginnen, ist es wichtig, den folgenden Prozessablauf zu durchlaufen:
- Identifizieren Sie die Simulationsziele für Ihr spezifisches Projekt
- Bereiten Sie sich auf die Simulation vor, indem Sie:
- Parameter identifizieren
- Parameter modellieren
- Führen Sie die Prototyp-Simulation aus
- Führen Sie den Test durch (physikalischer Test zum Vergleich der tatsächlichen Leistung mit den Simulationsergebnissen)
- Erfassen Sie die Daten
- Vergleichen Sie die Testergebnisse mit den Modellparametern
- Identifizieren Sie neue benötigte Parameter
- Führen Sie die Simulation bei Bedarf erneut durch und erfassen Sie erneut die Daten
- Analysieren Sie die Daten
- Aktualisieren Sie die Modelle
- Bestimmen Sie, ob zusätzliche Parameter erforderlich sind
- Überprüfen Sie den Bereich der Parameterwerte als Sicherheitsprüfung
- Design-Updates
1.3. Kontinuierliche Integration
Kontinuierliche Integration oder Continuous Integration (CI) ist eine Entwicklungspraxis, bei der Entwickler häufig, vorzugsweise mehrmals täglich, Code in ein gemeinsames Repository integrieren. Jede Integration kann dann durch einen automatisierten Build und automatisierte Tests verifiziert werden. Automatisiertes Testen ist zwar nicht strikt Teil der kontinuierlichen Integration, wird aber in der Regel impliziert.
Ein wesentlicher Vorteil der regelmäßigen Integration ist, dass Sie Fehler schnell erkennen und leichter lokalisieren können. Da jede eingeführte Änderung typischerweise klein ist, kann die spezifische Änderung, die einen Fehler eingeführt hat, schnell lokalisiert werden.
In den letzten Jahren ist die kontinuierliche Integration zu einer Best Practice für die Softwareentwicklung geworden und wird von einer Reihe von Schlüsselprinzipien bestimmt. Dazu gehören Revisionskontrolle, Build-Automatisierung und automatisierte Tests. [3]
Kontinuierliche Integration stellt sicher, dass Ihre Software regelmäßig entwickelt und getestet wird. Die Methode kann Ihnen helfen, zu demonstrieren, dass Ihre Software das tut, was sie zu tun behauptet, und dass sie dies korrekt tut. Es hilft Ihnen auch, schnell Fehlerbehebungen und funktionellere Versionen Ihrer Software zu veröffentlichen. Die kontinuierliche Integration kann auch zur Automatisierung von Experimenten verwendet werden, die mit Hilfe von Software ablaufen. [4]
1.4. Sind Simulation und automatisiertes Testen ausreichend?
Wenn wir Simulation und automatisierte Tests kombinieren und diese Szenarien regelmäßig ausführen, können wir davon ausgehen, dass eine bestimmte Qualität erreicht wurde. Aber ist das ausreichend, angesichts des aktuellen Konkurrenzkampfes auf dem Markt? Bei bestimmten Produkten ist dies der Fall, aber bei großen Systemen möglicherweise nicht. Aufgrund der Komplexität dieser großen Systeme können viele Szenarien übersehen und erst zu spät entdeckt werden, wenn die Kosten für die Behebung viel höher sind und sie das Image des Unternehmens beeinträchtigen können.2. Einführen von Randomisierungen in die Testumgebung
Um die Qualität und Stabilität großer Systeme zu verbessern, schlagen wir vor, die bereits vorhandenen Techniken um einen Zufallsinput zu ergänzen.
Das Random-Testing ist eine Black-Box-Testentwurfstechnik, bei der die Testfälle immer zufällig durch einen Algorithmus (treffend „Pseudo-Zufallsgenerierung“ genannt) ausgewählt werden, der einem Betriebsprofil entspricht. Diese Technik des Random Testing wird meist für nicht-funktionale Testattribute, wie Leistungs- und Zuverlässigkeitswerte, verwendet.
Für kleine Systeme macht das Random-Testing keinen Sinn, da es eher (wenig überraschend …) zufällige Ergebnisse liefert. Aber für größere Systeme könnte sie große Vorteile bringen, wenn die Pseudozufälligkeit richtig ausgeführt wird.
Kurz gesagt, Sie würden Ihr System über einen längeren Zeitraum laufen lassen, und jedes Modul würde in zufälligen Zeitabständen Ereignisse erzeugen. Wenn dies bereits in den frühen Phasen der Produktentwicklung geschieht, wird es die Qualität erheblich verbessern und die Kosten reduzieren, da es Fehler finden kann, ohne zu viel Aufwand in die Definition aller möglichen Szenarien zu stecken.
Unter diesem Link finden Sie einen interessanten Ansatz zur automatisierten Testgenerierung mittels Random Testing.
“So, when you’re testing your program systematically, the problem that you tend to have as a tester is you think like a good user, you tend to write test inputs that correspond to common cases in the program. But when we’re looking for things like security bugs, what we really want to do is to act like bad users, like malicious hackers or other people that are trying to break the system.”[5]
Sie könnten auch nach Wettlaufsituationen (race conditions) suchen, oder nach dem einen in einer Million Fällen, in denen Ihre App fehlschlägt. Die adaptive Eingangsgenerierung (bei Kenntnis des Spektrums und des Umfangs der Eingänge, die man wählt) kann eine große Verbesserung der zufälligen Eingangsgenerierung bringen.
2.1. Die grundlegende Lösung
Eine Gesamtlösung würde folgende Schritte umfassen (sie kann jedoch auf die Bedürfnisse des jeweiligen Produkts zugeschnitten werden):
- Erstellen Sie eine simulierte Umgebung der Hardware und integrieren Sie diese mit der Software.
- Definieren Sie einen Regelsatz zur Erzeugung von Systemereignissen und -inputs. Hierzu können wir zwei Kategorien unterscheiden:
- Normale Arbeitsbedingungen: Inputs, die das Modul regelmäßig von außen erhält (normale Benutzerinteraktion, korrekte Sensorwerte usw.)
- Fehlerbedingungen: Inputs, die auftreten, wenn etwas schief läuft (Hardware-Fehler, Fehlbedienung des Geräts usw.)
- Erweitern Sie die Simulation, indem Sie die Ereignisse und Inputs kontrolliert randomisiert einspeisen. Überlegen Sie sich verschiedene Situationen, die eintreten können, und erzeugen Sie Ihre Inputs innerhalb dieser Spielräume.
- Erstellen Sie automatisierte Tests auf Basis dieser simulierten Umgebung, sowohl mit einer vordefinierten Ereignisfolge als auch mit zufälliger Ereigniseingabe. Hier können Sie einige Szenarien definieren, abhängig davon, was benötigt wird (verbesserte Qualität, Stabilität, Leistung, Code-Integrität, usw.)
- Verwenden Sie kurz andauernde Simulationen/Tests, um Code-Aktualisierungen zu validieren. (Beziehen Sie das Bauen der Lösung mit ein) → BnT / „build and test“)
- Verwenden Sie regelmäßig komplexe Szenarien, um das Gesamtprodukt zu testen. (Kombination aus vordefinierter Reihenfolge von Ereignissen mit zufällig generierten Ereignissen.)
2.2. Vorteile
- Schnelleres Auffinden von eher seltenen Fehlerfällen, wie z. B. Wettlaufsituationen, als bei regulären automatisierten Tests
- Es weist keine Verzerrungen auf. Da die Inputs pseudozufällig sind, konzentrieren sich die Tests nicht darauf, ob die Leute wissen, wie das System funktioniert, was bedeutet, dass es leichter zu knacken sein kann.
- Der Einsatz von weniger Hardware und der geringere Zeitaufwand, der für die Hardware aufgebracht wird, können die Kosten erheblich senken
- QA-Ingenieure können ihre Zeit mit der Analyse von Fehlern verbringen, anstatt unendlich viele Tests durchzuführen
2.3. Nachteile
- Benötigt Ressourcen für Entwurf und Implementierung
- Muss zusammen mit dem Produkt aktualisiert werden
- Diese Technik stellt ein Problem für die kontinuierliche Integration dar, wenn bei jedem Test unterschiedliche Inputs randomisiert ausgewählt werden.
3. Zwischenfazit
Durch das Hinzufügen eines unverfälschten Random-Inputs zu automatisierten Tests können Sie die Qualität von großen Systemen mit einem geringeren Kostenaufwand verbessern. Der Mehrwert dieser Pseudo-Zufallstests ergibt sich aus der früheren Erkennung seltener Probleme und der hohen Rate der Erkennung von Leistungsproblemen.4. Azure zur Unterstützung der Simulation von zufallsgenerierten Tests verwenden
Es kann sich als schwierig erweisen, eine Simulationsumgebung mit den neuesten Änderungen im gesamten Unternehmen auf dem neuesten Stand zu halten, wenn jeder sein eigenes Szenario neu generiert. Glücklicherweise kann das Arbeiten über die Cloud dieses Risiko vermindern. Lassen Sie uns anschauen, wie wir mit Azure eine Simulationsumgebung einrichten und über das gesamte Unternehmen ausbreiten können.4.1. Eine virtuelle Maschine als Basis erstellen
Zunächst müssen Sie eine virtuelle Maschine erstellen, auf der Sie Ihre Simulation ausführen werden. Dies kann einfach über das Azure-Portal erfolgen. Bei der Erstellung der virtuellen Maschine müssen Sie die für die Ausführung der Simulation benötigten Ressourcen berücksichtigen und das beste Leistungs-/Kostenverhältnis finden. Weitere Informationen zum Erstellen von virtuellen Maschinen finden Sie hier.- Geben Sie ihr über einen generischen Benutzer Zugriff auf Ihre Versionsverwaltung, so dass jeder die Simulation ausführen kann, ohne ständig seine Anmeldedaten eingeben zu müssen.
- Verwenden Sie Skripte (bat, PowerShell), um die neueste Version Ihrer App zu erhalten, zu konfigurieren und zu installieren.
- Verwenden Sie ein Speicheraccount, um die Ergebnisse zu sichern (weitere Informationen zum Kopieren von Daten in die Cloud finden Sie hier.
- Für den Fall, dass die Simulation, die Sie ausführen möchten, automatisch eingerichtet wird, können Sie eine automatische Abschaltung konfigurieren (Details finden Sie hier.)
4.2. Ihre eigene Image-Datenbank anlegen
Der nächste Schritt besteht darin, eine gemeinsame Image-Galerie zu erstellen, in der Sie die Definitionen Ihrer virtuellen Maschine ablegen. (Für mehr Informationen besuchen Sie diese Seite.) In der Image-Galerie werden die Images aller virtuellen Maschinen mit einer vorkonfigurierten Testumgebung gespeichert. Auf diese Weise kann jeder im Unternehmen auf die Testumgebung zugreifen, ohne sie jedes Mal neu konfigurieren zu müssen, wenn sich etwas ändert. Sie können einfach eine virtuelle Maschine bereitstellen und die Simulation direkt ausführen. Damit ist sichergestellt, dass alle am Prozess Beteiligten die gleichen Grundeinstellungen haben und auch die Umgebung immer auf dem neuesten Stand ist.4.3. Hinzufügen eines Images einer virtuellen Maschine zu Ihrer Image-Datenbank
Nachdem die Galerie erstellt wurde, können Sie Definitionen für virtuelle Maschinen hinzufügen. Hier definieren Sie die Spezifikationen für die virtuelle Maschine, auf der verschiedene Arten von Simulationen ausgeführt werden sollen. Beachten Sie, dass Sie eine vorhandene virtuelle Maschine benötigen, von der Sie das Image erstellen können.
Arten von Simulationen, die infrage kommen (jedoch nicht ausschließlich):
- Aktuellste Version des Codes
- Freigabeversionen
- Kundenkonfigurationen
- Eine einfache Konfiguration (nur was benötigt wird, um die Kernfunktionen zum Laufen zu bringen)
- Eine komplexe Konfiguration (um zu prüfen, wie sich das System bei starker Belastung verhält)
Prüfen Sie für jeden der oben genannten Typen, ob die Einführung eines zufallsgenerierten Inputs den Mehrwert der Überprüfung erhöhen kann.
Bei diesem Schritt wären die für die Art der Simulation benötigten Ressourcen zu berücksichtigen. Sie können die Vorgaben unter der Registerkarte „Veröffentlichung“ einstellen. Dies gibt den Benutzern des Images eine Vorstellung davon, welches System sie für die Simulation einrichten sollten.
Eine Möglichkeit besteht darin, ein Image der zuvor erstellten virtuellen Maschine zu Ihrer Datenbank hinzuzufügen. Gehen Sie zur Konfiguration der virtuellen Maschine im Azure-Portal und wählen Sie „Capture“.
4.4. Erstellen einer virtuellen Maschine aus einem Image in der Galerie
Aus dem zuvor erstellten Image können wir wie folgt neue virtuelle Maschinen erstellen: Wählen Sie das Image aus der Image-Datenbank aus4.5. Ausführen der virtuellen Maschine und Starten der Simulation
Da Sie nun die virtuelle Maschine erstellt haben, müssen Sie sie starten und eine Verbindung zu ihr herstellen, um Ihre Simulation auszuführen. Klicken Sie zunächst auf die Schaltfläche „Start“, um die virtuelle Maschine vorzubereiten und zu starten, und verwenden Sie dann die Schaltfläche „Connect“, um sich mit ihr zu verbinden.4.6. Verwendung von Skripten zur Optimierung der Image-Erstellung
Nachdem wir nun gesehen haben, wie Images zum Ausführen von Simulationen verwendet werden können, können wir den Prozess weiter optimieren, indem wir Azure-PowerShell-Skripte verwenden, um alle oben genannten Schritte automatisch auszuführen. Dies wird in den folgenden Tutorials von Microsoft sehr gut erklärt:4.7. Fazit
Um die Kosten niedrig zu halten und gleichzeitig die Qualität zu erhöhen, kann Azure ein sehr nützliches Werkzeug sein, um eine gute Umgebung für Simulationstests zu erhalten, besonders wenn Sie eine große Anzahl von Szenarien abdecken müssen.
- Es kann aufgrund der Redundanzkonfiguration eine nahezu 100%ige Betriebszeit bieten.
- Sie zahlen nur für die Zeit, in der die Maschinen genutzt werden.
- Sie müssen sich nicht um Hardware-Upgrades oder fehlerhafte Hardware kümmern.
- Jeder in Ihrer Organisation kann auf genau jenes Testszenario zugreifen, das benötigt wird.
- Sie können beliebig viele Tests, die benötigt werden, parallel laufen lassen, ohne Ihr System zu überlasten.
Referenzen:
[1] https://www.kovair.com/blog/how-to-build-a-successful-continuous-testing-environment/
[2] https://www.embedded.com/what-you-need-to-know-about-automated-testing-and-simulation/
[3] https://www.cloudbees.com/continuous-delivery/continuous-integration
[4] https://software.ac.uk/using-continuous-integration-build-and-test-your-software