Autor: Björn Scherer
Kein Testprojekt kommt ohne Testdaten aus und der Bedarf scheint immer weiter zu steigen. Generiert man Testdaten auf Vorrat, müssen sie aufwendig verwaltet werden (Testdaten-Management). Oftmals sind Datenstrukturen komplex und realistische Daten nur schwierig anzulegen. Im Folgenden wird ein Ansatz vorgestellt, der mittels „ondemand Cloning“ versucht, die Nachteile der klassischen Ansätze loszuwerden.
Herausforderungen bei Testdaten
- Komplexität: Mit steigender Komplexität der zu testenden Anwendungen steigt auch die Komplexität der verwendeten Daten, was sich auf die Testvorbereitung auswirkt. Oft sind synthetische Daten nur bedingt einsetzbar, realistische und produktionsnahe Daten allerdings oftmals zu komplex, um sie in der Tiefe anlegen zu können.
- Menge: Aus unterschiedlichen Gründen (Fast Feedback Loops, Automatisierung, kürzere Release-Zyklen, etc.) steigt die Zahl an Testdurchführungen und damit auch der Bedarf an Testdaten immer weiter an. Das Problem vervielfältigt sich zusätzlich mit jeder weiteren Umgebung/Stage.
- Verbrauch: Da bei schreibenden Use-Cases die verwendeten Daten verändert werden, sind sie für den gleichen Use-Case nicht mehr verwendbar. Beispielsweise kann ein bereits gekündigter Vertrag für den Use-Case „Vertragskündigung“ (ohne weitere Pflege) nicht mehr verwendet werden. Die Daten werden sprichwörtlich „verbraucht“.
- Produktionsnähe: Auf Test-Stages können Daten oftmals nur bedingt die Komplexität von gewachsenen Datenstrukturen in der Produktion widerspiegeln. Kommt es bei einer Anwendung in der Produktion zu Problemen bei der Verarbeitung solcher Datenstrukturen, ist es nicht selten eine Herausforderung, diesen Fehler auf einer Test-Stage nachzustellen. Der Versuch, die ursächlichen Daten aus der Produktion in eine Test-Stage zu bringen, um den Anwendungsfehler dort zu reproduzieren und beheben zu können, stellt eine technische Herausforderung dar und wird auch durch rechtliche Rahmenbedingungen (DSGVO) oft noch erschwert.
- Übertragbarkeit: Oft ist der Datenbestand zwischen verschiedenen Test-Stages sehr heterogen, da es an Mechanismen fehlt, valide Datenstrukturen zwischen den Stages zu übertragen. Somit kann es passieren, dass Testfälle, die konkrete Daten verwenden, auch an eine spezielle Stage gebunden und damit ebenfalls nicht übertragbar sind.
Es gibt sicherlich noch weitere Herausforderungen im Umgang mit Testdaten. Die oben aufgeführte Aufzählung zeigt allerdings schon, wie vielfältig die Herausforderungen sein können und warum viele Projekte Schwierigkeiten damit haben.
Klassische Ansätze zur Lösung:
Klassischerweise gibt es zwei Ansätze zum Umgang mit Testdaten:
Selektion
Bei diesem Ansatz werden bestehende Daten anhand bestimmter Kriterien selektiert. Dadurch ist man stark vom Ist-Zustand einer Stage abhängig. Die Definition der Selektionskriterien stellt eine zusätzliche Herausforderung dar: Um die richtigen Daten zu finden (und abzugrenzen), bedarf es sowohl fachlicher Kenntnisse des Use-Case, aber auch genauer Kenntnisse der (technischen) Datenstrukturen. Die hierzu benötigten Abfragen können schnell komplex werden. Zur manuellen Nutzung ist dies meist nur einem bestimmten Personenkreis möglich. Zur Nutzung im Automatisierungsumfeld kann es schnell aufwendig werden, dies für viele Einzelfälle umzusetzen.
Erzeugung
Wenn die Daten nicht in der benötigten Form oder Menge im System vorhanden sind, müssen sie angelegt werden. Die Anlage erfolgt meist mit Anlageskripten, die für jede benötigte Datenkonstellation gesondert und teilweise sehr aufwendig erstellt werden müssen. Aus dem Bedarf werden hierzu Testdaten-Klassen abgeleitet und jeweils Anlage-Skripte erstellt. Mit diesen Skripten können anschließend größere Mengen an Datensätzen auf Vorrat im System angelegt werden. Ab diesem Moment bedarf es jedoch einer entsprechenden Verwaltung des erzeugten Vorrates, um die Verteilung auf Nutzergruppen und ausreichende Menge (bei Verbrauch) sicherzustellen.
Eine solche synthetische Anlage funktioniert für einfache Daten-Konstellationen gut, kann aber schnell an Grenzen stoßen. Zum Beispiel, wenn es um komplexe, reale Konstellationen geht, die über mehrere Jahre/Vertragsversionen/Tarifgenerationen hinweg gewachsen sind und gepflegt werden müssen. Zusätzlich wächst der Aufwand für die Anlage und Verwaltung für jede weitere Stage.
Das Problem wird besonders bei der Nutzung in automatisierten Testfällen deutlich: Listing 1 zeigt einen beispielhaften Testfall mit fachlichen Keywords (hier in der Notation des Testtools FitNesse). Die farblich markierten Stellen zeigen die konkreten Daten, die im Testfall genutzt werden. Diese stellen harte Abhängigkeiten zu einem konkreten Datensatz auf einer bestimmten Stage dar. Somit ist der Testfall nicht mehr auf andere Stages übertragbar.
Ein neuer Ansatz muss her
Nachfolgend wird ein On-demand- und Cloning-Ansatz vorgestellt, der das Ziel hat, die genannten Nachteile zu vermeiden. Um dies zu erreichen, werden im Vergleich zu den klassischen Ansätzen zwei Aspekte grundlegend geändert:
- On-demand statt auf Vorrat: Die Daten werden nicht mehr massenhaft vorab angelegt, sondern einzeln und erst im Moment der Nutzung.
- Cloning statt Anlage per Skript: Die Daten werden auch nicht „von außen“ künstlich mit Skripten angelegt, sondern als bereits im System befindliche, vorab identifizierte Daten dupliziert bzw. geklont.
Kern des Ansatzes ist die Einrichtung eines Testdatenkatalogs, der mit relevanten Datensätzen als Template befüllt wird.
Datensätze, die für einen konkreten Testfall relevant sind, werden einmalig (manuell) im System selektiert und mit einer Referenz auf die ID des Hauptgeschäftsobjekts (Kunde, Vertrag, etc.) im Katalog hinterlegt (siehe Grafik 1). Ab diesem Moment werden die Daten nur noch als Template benutzt und nicht mehr verändert1.
Grafik 1: Darstellung des Testdaten-Kataloges innerhalb der DB und die Nutzung der Daten im Testfall
Zum Zeitpunkt der Verwendung wird der Template-Datensatz (bspw. Vertrag mit ID 0815) nicht direkt verwendet, sondern zunächst mittels Cloning eine Kopie erzeugt (Vertrag mit neuer ID 1337). Der Cloning-Mechanismus kennt die Relationen in der Datenstruktur und iteriert über die verlinkten Tabellen, bis er eine ganzheitliche Kopie des Datennetzes erstellt hat. Im Testablauf wird dann nur noch die Kopie der Daten genutzt, statt des Originals. Dies sichert, dass die Template-Daten unverändert bleiben und nachhaltig wiederverwendbar sind (siehe Grafik 1).
Unser Beispiel-Testfall (Listing 1) braucht also nicht mehr den konkreten Datensatz „Vertrag 0815“, sondern er braucht einen Datensatz, der vergleichbar ist mit „Vertrag 0815“. Dieses Kriterium wird von jedem Klon genauso erfüllt wie vom Original.
Aber Achtung: Trotz des Anspruchs, eine „gleiche“ Datenkonstellation durch das Klonen zu produzieren, können die Daten aufgrund von technischen Beschränkungen (Primärschlüssel, Sequenzen etc.) nicht identisch sein. So darf es bspw. keine zwei User-Accounts mit derselben E-Mail-Adresse geben, genauso wie es nicht zwei Verträge mit der gleichen Vertragsnummer geben darf. Daher müssen nach dem Klonen die geklonten Daten zunächst ausgelesen werden, um sie dann im Testfall weiterverwenden zu können.
Listing 2 zeigt die benötigten Anpassungen am Beispiel-Testfall: Im ersten Schritt werden die Referenzdaten (angegeben durch Vertrag mit ID „0815“) geklont und die Kopie gelesen. Um die neuen, geklonten Daten im weiteren Verlauf nutzen zu können, muss sich der Testfall die Daten merken können. Dies wird durch die Nutzung einer Art Testdaten-Container realisiert (Objekt-Variable $td), von dem die konkreten Daten (im Beispiel: Account, Vertragsnummer, etc.) im Verlauf abgefragt werden können. Man kann diese Veränderung der Testfälle als Weiter-entwicklung vom konkreten Testfall zum logischen/abstrakten Testfall beschreiben (vgl. ISTQB ® Glossar).
Zwischenstand
Mit den genannten Änderungen im Handling von Testdaten können bereits einige der genannten Nachteile vermieden werden:
- Menge und Vorratsverwaltung: Die on-demand-Erzeugung ersetzt die Vorab-Erzeugung. Wird kein Vorrat erzeugt, muss dieser auch nicht aufwendig verwaltet werden. In Kombination mit dem Cloning fällt zusätzlich auch die ebenfalls aufwendige Vorbereitung weg (Erstellung und Ausführung von Anlage-Skripten).
- Selektion: Die aufwendige Selektion zu jeder Testdurchführung fällt weg bzw. reduziert sich auf eine initial einmalige Selektion zur Ablage im Testdaten-Katalog, wodurch der Datensatz zum Template wird.
- Verbrauch: Die Daten im System (bzw. die im Katalog) sind nicht mehr anfällig für Veränderungen oder Verbrauch. Sie werden nicht mehr aktiv verwendet, sondern dienen nur noch als Klon-Vorlage. Die Klon-Ergebnisse werden nicht wiederverwendet und können daher nach Belieben verändert werden.
- Komplexität: Seltene Fälle und gewachsene Datensätze, die sonst zu aufwendig waren, sind durch das Klonen auch kein Problem mehr.
Übertragbarkeit
Ein bisher noch nicht adressierter Bedarf ist die Übertragbarkeit der Tests auf mehrere Stages. Voraussetzung dafür ist, dass die benötigten Testdaten ebenfalls übertragbar sind.
Im bisher beschriebenen Klonvorgang wurden jedoch nur innerhalb einer Stage Daten geklont. Quelle und Ziel waren also die gleiche, lokale Stage. Zur Lösung müssen also lediglich Quell- und Ziel-Stage (optional) parametrisierbar gestaltet werden und man schafft die Möglichkeit, einen Datensatz direkt in den Testdaten-Katalog einer anderen Stage zu replizieren, um ihn im Anschluss mit dem bewährten Klon-Mechanismus lokal zu vervielfältigen (siehe Grafik 2).
Grafik 2: Die Erweiterung des lokalen Clonen auf ein „Direkt-Clonen“ zu anderen Umgebungen / Stages als Zwischenschritt (mit Problemen).
Bei der Replikation zu einer anderen Stage ändern sich allerdings (wie beim lokalen Klonen) einige (Referenz-) Daten. Innerhalb der gleichen Stage ist dies kein Problem, da die geänderten Daten wie beschrieben vor der Nutzung im Testfall gelesen werden. Auf einer neuen Stage wird hierdurch aber auch die Referenz-ID geändert, die in unseren Testfällen bisher hartcodiert ist und dazu dient, das zu klonende Daten-Template zu selektieren (siehe Vertrag “0815” in Listing 2).
Um diesen Punkt zu adressieren, werden die Einträge im Testdaten-Katalog um logische Namen ergänzt. Der Vertrag “0815” aus den Listings erhält bspw. den logischen Namen “referenz_kunde_xy”. Beim Replizieren zwischen den Stages bleibt der Name erhalten, erhält aber auf jeder Stage seine eigene, neue Referenz-ID.
Der Clone-Mechanismus muss lediglich vorab dieses Mapping nutzen, um über den Namen die lokal gültige Referenz-ID zu ermitteln und kann dann wie gewohnt die selektierten Daten klonen.
Das gleiche Prinzip wird auch auf die Testfälle angewandt, um diese übertragbar zu machen. Hier werden ebenfalls nur noch die neu eingeführten Referenznamen, statt der IDs, genutzt (siehe Listing 3).
Hinweis: In der Praxis hat es sich bewährt, bestimmte Namensschemata oder Präfixe zu verwenden (bspw. Vertragsart, Produkt-Merkmale, Name des Dev-Teams, etc.), um die Inhalte expliziter zu machen und Einträge einfacher zu finden und abgrenzen zu können.
Produktionsnähe
Mit der Möglichkeit, Daten zwischen verschiedenen Stages übertragen zu können, entsteht auch der Bedarf nach realistischen Daten und der Wunsch, diese aus Produktion gewinnen zu können. Rein technisch gesehen ist die Produktion für den Klonmechanismus nur eine weitere Stage. Allerdings gibt es hier aus organisatorischer Sicht einiges zu beachten.
a) Produktion als Klonziel: Die oberste Priorität ist, dass der Produktionsstand unverändert bleibt. Daher muss im Algorithmus der Klonmechanik die Produktion explizit als Ziel-Stage ausgeschlossen werden.
b) Produktion als Klonquelle: Sobald Daten von der Produktion zu einer anderen Stage geklont werden sollen, sind weitere Richtlinien zu beachten, um den diversen rechtlichen Anforderungen (bspw. DSGVO-konforme Anonymisierung, etc.) gerecht zu werden.
So kann die Möglichkeit entstehen, echte Datenkonstellationen in die Test-Stages zu bringen.
Skalierung
Skaliert man das Verfahren auf viele Umgebungen / Stages parallel, zeigt sich eine weitere organisatorische Schwäche:
Werden Daten immer nur direkt zwischen den Stages übertragen, führt jede Stage ihren individuellen Testdaten-Katalog. Damit wird es schnell unübersichtlich, welche Referenzdaten auf welchen Stages vorhanden sind bzw. wo die Quelle eines bestimmten Datensatzes ist, wenn er auf einer Stage fehlt.
Um diesen Punkt zu adressieren, muss das Konzept erweitert werden: Es wird eine zentrale Instanz des Testdaten-Katalogs eingeführt. Der sogenannte “Testdaten-Master” und seine Daten werden nicht aktiv in Tests verwendet, er dient lediglich als zentrale Ablage der Referenzdaten bzw. Templates (siehe Grafik 3).
Grafik 3: Zur Skalierung auf viele Stages wird der Ansatz um eine zentrale „Master“-Instanz erweitert.
Entsteht ein neuer Referenzdatensatz (bspw. “vip_kunde_abc”), so werden diese Daten einmalig im Master abgelegt und können von da aus mittels des Referenznamens auf jede andere Ziel-Stage repliziert werden. Soll der Datensatz auf einer Stage verwendet (geklont) werden, prüft die Klonmechanik zunächst die Verfügbarkeit im lokalen Katalog. Ist dieser noch nicht vorhanden, wird die Replikation aus dem Testdaten-Master angestoßen und im Anschluss normal geklont.
Fazit
Mithilfe der Umstellung des Testdaten-Handlings von der Erzeugung auf Vorrat und Verwaltung hin zu einem Verfahren mit Cloning on-demand (mittels lokalem Testdaten-Katalog und einem zentralen Testdaten-Master) konnten die vielen geschilderten Herausforderungen im Umgang mit Testdaten (Menge, Verwaltung, Komplexität, Übertragbarkeit und Produktionsnähe) adressiert werden. Das Handling ist nun einfacher, flexibler und deutlich weniger aufwändig.
1 Anmerkung: Sofern möglich, sollten diese Template-Daten auch gegen Veränderung gesperrt werden. Die technischen Möglichkeiten sind hier stark vom verwendeten DBMS abhängig.