Bekanntlich verspricht die Testautomatisierung kürzere Testzeiten, einen größeren Testumfang und konstantes Feedback über die Softwarequalität, um sich länger und gründlicher mit neuen Funktionalitäten zu befassen oder sich einfach mehr Slack-Time zu schaffen.
Auch wenn die Return-on-Investment-Kennzahlen für Testautomatisierung sprechen, ist ein wirtschaftliches Fiasko bei falscher Umsetzung nicht vollständig ausgeschlossen. Testautomatisierung ist beispielsweise ohne Testdatenmanagement kaum praktikabel. Somit kann die automatisierte Testdatengenerierung als Vervollständigung der Testautomatisierung betrachtet werden.
Genau wie das manuelle Testen ist manuelles Erstellen und das Eingeben von Testdaten zeitintensiv und verglichen mit der automatisierten Testdatengenerierung langsam und fehleranfällig.
Die Überlegung, die Testdaten manuell zu erzeugen, wird verworfen, sobald ein höheres Testdaten-Volumen oder gute Wartbarkeit notwendig ist. Gehen die manuell erzeugten Testdaten verloren, müssen sie wieder mühsam manuell ins System eingetippt werden.
All dies sollte genügen, um sich ernsthaft mit der automatisierten Testdatengenerierung zu beschäftigen.
Vor- und Nachteile einer Testdatengenerierung zur Laufzeit
Mit der automatisierten Generierung synthetischer Testdaten lassen sich die Testdaten von anderen Systemen entkoppeln und beliebig oft wiederverwenden. Das heißt, dass es weder lästiges Suchen nach den „passenden“ Daten gibt noch werden die Daten „verbraucht“ oder „veralten“.
Zu den weiteren Vorteilen der synthetischen Testdatengenerierung zählen:
- keine separate Datenhaltung pro Testumgebung nötig,
- Vorhandensein aller notwendigen Daten (z. B. pro Äquivalenzklasse),
- keine externe Datenhaltung nötig,
- kein Warten auf neu aufzusetzende und verschlüsselte Testumgebungen sowie eine mögliche Datenanonymisierung während der Laufzeit des Tests.
Die meisten Implementierungen unterscheiden sich darin, wann die Testdaten generiert werden. Eine Möglichkeit ist, die Testdaten vor der Testphase zu erzeugen und anschließend die Testfälle laufen zu lassen. Dabei besteht die Gefahr, dass alle Testfälle fehlschlagen oder kein Testfall ausgeführt wird, falls die Testdatengenerierung nicht erfolgreich ist. Des Weiteren kann leicht übersehen werden, dass mehrere Testfälle von den gleichen Testdaten abhängig sein könnten und die Generierung aller Testdaten viel Zeit in Anspruch nehmen könnte.
Dies kann mit einer stärkeren Kopplung von Testdaten und Testfällen verhindert werden, indem die Testdatengenerierung während der Laufzeit im Testfall selbst passiert. Dabei werden die Testdaten vor der Ausführung eines jeden Testfalls generiert und nach der Ausführung (idealerweise) gelöscht. Diese frühzeitige Verknüpfung der Testfälle mit Testdaten wirkt sich auch positiv auf die Analyse der Testergebnisse aus. Die Fehler sind einzelnen Testfällen eindeutig zuordenbar und leicht mit einzelnen Bugs/Defects verknüpfbar.
Dem gegenüber steht wohl der größte Nachteil dieser Methode: der des längeren Testfall-Codes. Dadurch entstehen höhere Wartungsaufwände und höhere Testdurchlaufzeiten. Da diese Art der Testdatengenerierung nicht auf jeden Testfall angewendet werden kann, kann eine hybride Testdatenverwaltung entstehen, welche den Wartungsaufwand für die Testdaten ebenfalls erhöht. Längere Testdurchlaufzeiten können jedoch mit gängigen Parallelisierungstechniken verringert werden.
Unabhängig davon, welche Möglichkeit gewählt wird, können all die relevanten Testdaten vor und/oder nach jedem Testlauf zur Gänze gelöscht werden. Dauert dieser Löschvorgang zu lange und verhindert somit beispielsweise den Deployment-Prozess, kann er auf einen späteren günstigeren Zeitpunkt verlegt werden.
Mithilfe verschiedenster Tools können benötigte Testdaten programmtechnisch erzeugt werden. Am Beispiel der Open-Source-Library „Faker“ [GitH] wird nachfolgend gezeigt, wie synthetische Daten erzeugt werden können.
Faker – Daten per Zufallsgenerator?
Faker [FDoc] ist eine für Python (ab Version 3.5) einsetzbare Library, welche verschiedene Methoden zur Verfügung stellt, mit denen syntaktisch korrekt Testdaten generiert werden können. Die Installation von Faker erfolgt mit:
pip install Faker
Bei der Generierung kann eine von 75 Landessprachen angegeben werden, was beim Testen international verwendeter Applikationen von Relevanz sein kann.
Faker stellt sogenannte Standard-Provider zur Verfügung, welche in 23 Kategorien definierte Methoden beinhaltet (siehe Abbildung 1). Diese können vom Anwender parametrisiert werden.
Abb. 1: Standard-Provider - 23 Kategorien
Alleine der Standard-Provider faker.providers.date_time
beinhaltet 36 Methoden zur Generierung eines Datums. Beispiel-Methoden:
- fake.date_between(start_date=‘- 30y‘, end_date=‘today‘)
- fake.date_of_birth(tzinfo=None,minimum_age=0, maximum_age=115)
- fake.day_of_week()
Mithilfe der Kategorie faker.providers.geo
lassen sich auf einfache Art und Weise geografische Koordinaten (samt Stadt, Region, Staat falls notwendig) generieren, siehe Listing 1.
Faker.seed()
for _ in range(2):
fake.local_latlng()
…
('37.95143', '-91.77127', 'Rolla',
'US', 'America/Chicago')
('44.73941', '-93.12577', 'Rosemount',
'US', 'America/Chicago')
Die Kategorie faker.providers.credit_card
versieht Testfälle mit allen notwendigen Informationen rund um Kreditkarten, wie Verfallsdatum, Kartennummer, Kreditkartenherausgeber und Kartenprüfnummer, siehe Listing 2.
Faker.seed()
for _ in range(2):
fake.credit_card_full()
…
'VISA 13 digit \n Leonardo Mälzer \n
4852977650571 09/25 \n CVC: 802'
'American Express \n Carmine Pruschke \n
344734554565225 07/30 \n CVC: 9836'
Wer mit Standard-Providern kein Auslangen findet, kann zusätzlich auf Community-Provider zurückgreifen. Alternativ können Provider selbst erstellt und mit eigenen Datenlisten hinterlegt werden, siehe Listing 3.
#eine neue Provider-Klasse erstellen
class MeinNeuerProvider(BaseProvider):
def Wetter(self):
return ‚sonnig‘
#den neue Provider der faker Instanz zuweisen
fake.add_provider(MeinNeuerProvider)
#den neuen Provider verwenden
fake.Wetter()
#sonnig
Auch wenn der eigentliche Zweck die zufällige Datengenerierung ist, besteht mit der Methode seed()
die Möglichkeit, immer den gleichen Wert ausgeben zu lassen, siehe Abbildung 2.
Abb. 2: Methode seed()
Faker-Bibliotheken werden für Java, PHP, Perl, Ruby und andere Sprachen angeboten.
Einsatz in der Praxis: Daten per Code
Wir wollen nun anhand eines Beispiels aus der Praxis den Einsatz von Faker bei einer kundenrelevanten Applikation demonstrieren. Kundenrelevante Applikation zählen spätestens seit Inkrafttreten der GDPR-Richtlinien 2018 [GDPR] compliance-seitig zu den kritischsten Systemen eines Unternehmens. Die Durchführung von Tests darf ausschließlich mit anonymisierten, besser noch mit synthetischen Testdaten erfolgen. Dennoch sollen die Daten realitätsnahe sein, wie Postleitzahlen, Kreditkartennummern, Adressen, usw. Bei Bedarf sollen länderspezifische Formate berücksichtigt werden können, wie unterschiedliche IBAN- oder VAT-ID-Nummern (ATxxx, DExxx). Faker bietet die ideale Lösung (während der Laufzeit eines Testfalls) neue Mitarbeiter mit synthetischen Daten zu erzeugen, um diese für weitere Testzwecke verwenden zu können.
Ein einfaches Beispiel zur Erzeugung von Mitarbeiterdaten zeigt Listing 4.
1 from faker import Faker # Faker importieren
2
3 class GenerateEmployeeData(unittest.Testcase):
4
5 def test_add_new_employee(self):
6 # Faker-Klasse für Deutschland
7 fake = Faker(‘de_DE’)
8 Faker.seed() # alle Werte zufällig
9
10 firstname = fake.first_name()
11 lastname = fake.last_name()
12 hiredate = fake.date_between(
start_date='today',end_date='+30d')
13 phonenumber = fake.phone_number()
14 mainstreet = fake.street_address()
15 maincity = fake.city_with_postcode()
16 email = fake.email()
17 iban = fake.iban()
Nach dem Import der Faker-Library (Zeile 1) wird angegeben, in welchem Landesformat (Zeile 7) Daten generiert werden und ob diese bei jedem Testlauf neu (Zeile 8) ermittelt werden sollen. In Abhängigkeit dieser Parameter würde Faker zum Beispiel die folgenden deutschlandspezifischen Werte erzeugen:
10 Ottfried
11 Gieß
12 2021-02-14
13 +49(0)2555 35928
14 Ilhan-Klemt-Ring 1
15 07649 Cuxhaven
16 kobeltcathrin@gmail.com
17 DE28079951370886809690
Fazit
Testdaten sind ein fester Bestandteil eines jeden Entwicklungsteams. Es ist nicht die Frage, ob sie gebraucht werden, sondern welche Qualität sie haben, ob sie datenschutzkonform sind und wie schnell sie bereitgestellt werden können.
Je realistischer die Testdaten sind, desto leichter lassen sich die Testergebnisse interpretieren. Es ist daher notwendig, das Testdatenmanagement effektiv zu gestalten. Ein wichtiger Aspekt davon ist der Einsatz eines Werkzeugs, wie zum Beispiel Faker, für Testdatengenerierung, um realistische Testdaten zu erzeugen.
Weitere Informationen
[FDoc]
https://faker.readthedocs.io/en/master/
[GDPR] General Data Protection Regulation, siehe:
https://www.ris.bka.gv.at/Dokumente/BgblAuth/BGBLA_2017_I_120/BGBLA_2017_I_120.pdf