Zum Inhalt springen

Suchen...

Warum Testautomatisierung Design Patterns braucht

Code zur Testautomatisierung verdient die gleiche Sorgfalt beim Design wie Produktionscode. Page Object, Builder, Facade und warum das Überspringen von Design Patterns Frameworks in Spaghetti verwandelt.

8 Min. Lesezeit
Cover für Warum Testautomatisierung Design Patterns braucht

Entwurfsmuster in der Testautomatisierung sind bewährte, wiederverwendbare Lösungen, die den Testcode strukturiert, lesbar und erweiterbar halten. Zu den wichtigsten Mustern gehören Page Object, das die Elemente einer Webseite in Klassen kapselt, Builder, der die Objekterstellung von der Darstellung trennt, und Facade, das einen einzigen Einstiegspunkt für gruppierte Funktionen bietet. Zu den unterstützenden Prinzipien gehören DRY (do not repeat yourself), KISS (keep it simple) und YAGNI (you aren’t gonna need it).

Das Wichtigste in Kürze

  • Entwurfsmuster geben Testautomatisierungsteams ein gemeinsames Vokabular an die Hand, so dass ein Problem durch die Benennung eines Musters (Builder, Singleton, Facade) gelöst werden kann, anstatt die Lösung von Grund auf neu zu erklären.
  • Spaghetti-Testcode ist das direkte Ergebnis des Verzichts auf Kapselung: Ohne Muster wie Page Object sind Selektoren und Methoden über die Tests verstreut und die Duplikation vervielfacht sich.
  • Für Testautomatisierungsframeworks gilt das YAGNI-Prinzip: Implementiere nur das, was jetzt gebraucht wird, und belasse die Erweiterbarkeit als strukturelle Option und nicht als einen Haufen ungenutzter Helferlein.
  • KI-Tools erzeugen überkomplizierten Code für die Testautomatisierung ohne explizite Einschränkungen in der Eingabeaufforderung, und ein menschlicher Ingenieur muss die Ausgabe immer noch überprüfen und umgestalten.
  • Die Entwurfsmuster der Gang of Four, die 1994 veröffentlicht wurden, sind nach wie vor direkt auf die Testautomatisierung anwendbar, einschließlich der Erstellungsmuster und des Pool-Objekt-Musters zur Verwaltung paralleler Web-Treiber-Instanzen.

Warum Entwurfsmuster in den Code der Testautomatisierung gehören

Code zur Testautomatisierung ist echter Code und verdient die gleiche Sorgfalt wie das Produktionssystem, das er prüft. Kostiantyn Teltov hat fast zwei Jahrzehnte mit dem Testen von Software verbracht und verfügt über einen technischen Hintergrund in C#, Java, JavaScript, TypeScript und Python. Sein Standpunkt ist klar: Kümmere dich um deinen Code für die Testautomatisierung, denn er wächst und überlebt den schnellen Prototyp, mit dem du angefangen hast.

Design Patterns erfüllen hier vier Aufgaben. Sie bieten dir eine bewährte Lösung, anstatt das Rad neu zu erfinden. Sie ermöglichen objektorientierte Prinzipien, was verhindert, dass der Code zu Spaghetti wird. Sie schaffen ein gemeinsames Vokabular im Team. Und sie unterstützen die Erweiterbarkeit, so dass das kleine Framework, das du heute baust, morgen skalierbar ist.

Der letzte Punkt ist der praktische Nutzen. Eine Testsuite, die als Prototyp beginnt, wird oft zum Rückgrat einer größeren Lösung. Mit Hilfe von Mustern kann sie wachsen, ohne unter ihrem eigenen Gewicht zusammenzubrechen.

Was das Page Object-Muster löst

Das Page Object ist das am weitesten verbreitete Muster in der Testautomatisierung von UI-Prozessen und dient dazu, Doppelarbeit zu vermeiden. Ohne dieses Muster würdest du alle deine Selektoren und Methoden direkt in deine Tests schreiben und sie jedes Mal wiederholen, wenn du denselben Bildschirm berührst.

Ein Page Object kapselt einen Bildschirm oder eine Webseite in einer Klasse. Wenn die Seite groß ist, teilst du sie in Unterklassen für die kleineren Teile auf. Die Selektoren und die Aufrufe des Web-Treibers befinden sich an einem Ort, und die Tests rufen sie auf.

Das funktioniert unabhängig von der Programmiersprache oder dem Test-Framework. Page Objects sind eine gemeinsame Grundlage, auf die fast jeder UI-Automatisierer als erstes zurückgreift, und genau deshalb sind sie der natürliche Einstieg in das Pattern-Denken.

Builder, Facade und Pool: drei wissenswerte Muster

Neben den Page Objects gibt es noch eine Handvoll weiterer Patterns, die in der Automatisierungsarbeit ihren Platz haben. Kostiantyn hebt den Builder und die Facade hervor und weist auf ein anderes Muster, den Objektpool, hin, der nicht zu den Gang-of-Four-Mustern gehört und ein spezielles Leistungsproblem aufzeigt.

Der Builder trennt die Objekterstellung von der Objektdarstellung. Die Analogie ist ein Burger: Aus einem Konstruktor baust du einen Cheeseburger oder einen Hamburger, indem du die gewünschten Teile zusammenfügst. In Tests liest sich das sehr sauber. Ohne ein komplettes BDD-Framework wie Cucumber oder SpecFlow zu verwenden, macht ein Builder die Testeinrichtung fast genauso lesbar, denn die Konstruktionsschritte geben vor, was der Test braucht.

Die Facade funktioniert wie eine Rezeption. Du kommst bei einer Klasse an und kannst von dort aus alles erreichen, was du brauchst. Bei einer API kannst du mit einer Facade zu Benutzern, Kunden oder Bestellungen navigieren, ohne in jedem Test die gleiche Initialisierung zu wiederholen. Du richtest die ähnlichen Klassen einmal ein, z. B. die REST-Request-Builder, und die Tests gehen über den einzigen Einstiegspunkt.

Der Objektpool ist ein Mittel gegen Speicherplatzmangel. Stell dir vor, du erstellst Web-Treiber parallel und schließt sie dann wieder und wieder, wobei der Speicher jedes Mal überläuft. Anstatt sie bei jedem Durchlauf zu erstellen und zu löschen, baust du einen Pool auf, entnimmst einen Treiber daraus, gibst ihn zurück und räumst den Pool am Ende auf. Die Idee ist einfach, wenn sie dir jemand zeigt.

Hier ist eine kurze Orientierung, wofür jedes Muster dient:

MusterProblem, das es löst
SeitenobjektDoppelte Selektoren und Web-Treiber-Aufrufe innerhalb von Tests
BuilderLangatmige Objekteinrichtung, schwer lesbare Testdatenkonstruktion
FacadeWiederholte Initialisierung und Navigation in vielen Klassen
Object PoolSpeicherverbrauch durch wiederholtes Erstellen und Zerstören von Objekten

Die Gang of Four-Muster haben immer noch Bestand

Muster, die 1994 veröffentlicht wurden, haben auch Jahrzehnte später noch ihre Gültigkeit. Die Gang of Four Erstellungsmuster sind ein guter Anfang: Singleton, Factory Method, Abstract Factory, Builder und Prototype.

Nicht alle von ihnen haben heute das gleiche Gewicht. Prototype zum Beispiel spielt in modernen Sprachen eine geringere Rolle, weil man Objekte unter der Haube auch ohne ihn kopieren kann. Die anderen werden immer noch regelmäßig verwendet, je nachdem, was du bauen willst.

Neben den Mustern gibt es zwei Designprinzipien. Das Prinzip der Abhängigkeitsinversion, das durch Dependency Injection umgesetzt wird, ist eines, das Kostiantyn als wichtig für Automatisierungsframeworks bezeichnet. Es geht nicht darum, alles anzuwenden, sondern den Katalog gut genug zu kennen, um das auszuwählen, was die Situation erfordert.

DRY und KISS sorgen für ehrlichen Testcode

Wiederhole dich nicht - das ist das Prinzip, das die meisten dieser Muster miteinander verbindet. Ein Page Object ist DRY in Aktion: Du vermeidest die Wiederholung von Element-Lookups und Web-Treiber-Methoden, indem du sie kapselst. Die gleiche Logik gilt auch für Assertions, die du wieder verwendest, oder für Datenbankaufrufe, die du häufig machst. Alles, was anfängt, wie Spaghetti auszusehen, ist normalerweise eine Wiederholung, die du in einen Helfer verschieben kannst.

Halte es einfach und bewahre die andere Flanke. Du entwirfst nicht das Produktionsprojekt. Du entwirfst die Tests dafür, und du schreibst keine Tests für deine Tests. Greife nur dann zu einem Muster, wenn das Problem es erfordert, und nicht, weil du es gerade gelernt hast und es verwenden willst.

Manchmal, vor allem wenn du etwas Neues lernst, wie z.B. ein neues Entwurfsmuster, versuchst du, es zu implementieren. Aber du musst dich immer fragen, ob es hier geeignet ist, denn manchmal wollen wir es überkomplizieren oder überdesignen.”

  • Kostiantyn Teltov

Du wirst es nicht brauchen, wenn das Set fertig ist. Baue, was du jetzt brauchst. Entwirf das Framework so, dass es erweiterbar ist, aber schreibe keine Helfer für Anwendungsfälle, die es noch nicht gibt. Verfrühtes Scaffolding ist eine eigene Form von Unordnung.

Wie KI mit Mustern umgeht und wo sie es überkompliziert

KI kann musterbasierten Code erstellen, aber nur, wenn du ihr den Kontext vorgibst und du das Ergebnis noch überprüfen musst. Die KI arbeitet mit Aufforderungen, sodass ein Muster nur dann in der Ausgabe erscheint, wenn du es verlangst. Wenn du den Kontext nicht angibst, wendet sie auch kein Muster an.

Die Verifizierung ist wichtiger als die Generierung. Kostiantyn bereitete einen Workshop vor, in dem ein Playwright-Framework von Grund auf mit ChatGPT erstellt wurde, und während der Vorbereitung funktionierte es gut. Einen Monat später, als er denselben Workshop mit einem kostenpflichtigen Tarif live durchführte, begann das Tool, zu kompliziert zu werden und eine Bedingung nach der anderen zu stapeln. Er musste die Ausgabe von Hand umgestalten und den Teilnehmern offen sagen, dass die generierte Version nicht korrekt war.

Die Lektion heißt Kontrolle, nicht Vermeidung. Die KI wird immer leistungsfähiger, aber der Ingenieur entscheidet immer noch, ob der generierte Code angemessen oder aufgebläht ist. Wenn du die Muster selbst kennst, kannst du diese Entscheidung treffen.

Vom Kopieren und Einfügen zum fließenden Lernen: Wie man Muster tatsächlich lernt

Die meisten Automatisierungsingenieure fangen mit dem Kopieren an. Du kommst in ein Team, deine älteren Kollegen geben dir Frameworks und Vorlagen, und du kopierst dir deinen Weg durch die ersten Arbeiten. Das ist ein normaler Anfang, aber kein Endzustand.

Der Weg nach vorne führt über drei Bereiche: objektorientierte Programmierung, wo sie gefordert ist, Datenstrukturen und Entwurfsmuster. Viele Testautomatisierungsentwickler/innen sind aus dem manuellen Testen und nicht aus der Entwicklung hervorgegangen, daher sind diese Grundlagen noch nicht immer vorhanden und es lohnt sich, sie bewusst aufzubauen.

Als Quellen verweist Kostiantyn auf das Originalbuch der Gang of Four über Design Patterns, die Website Refactoring Guru mit ihren illustrierten Erklärungen für mehrere Sprachen und kostenloses Material auf YouTube sowie Plattformen wie LinkedIn Learning und Udemy. Lesen zahlt sich immer noch aus, auch wenn das lange Lesen aus der Mode gekommen ist.

Die Methode, die für ihn funktioniert hat, war sozial. Sein Team traf sich einmal pro Woche im Büro, bereitete kurze Präsentationen vor und löste dann gemeinsam praktische Aufgaben nach einem vorgegebenen Muster. Kollegen zu finden, die dich antreiben, erweist sich als genauso nützlich wie jedes Buch.

Qualitätswissen verbreitet sich, wenn Teams ihre Blasen aufbrechen

Muster bleiben schneller haften, wenn ein Unternehmen sie mit anderen Teams teilt. An seinem Arbeitsplatz hat Kostiantyn geholfen, eine QA-Gilde zu gründen, die erste Gilde im Unternehmen, nachdem er sich bei der Personalabteilung dafür eingesetzt hatte.

Die Gilde hatte ein klares Ziel: Wissen verbreiten und Blasenbildung verhindern. Jedes Team kann anders arbeiten und sich auf seine eigenen Ansätze stützen, und diese Silos verhindern, dass sich gute Praktiken verbreiten. Eine Gilde ist ein Kanal, um sie zu verbreiten.

Damit sind wir wieder bei einem der vier Gründe, warum es überhaupt Muster gibt. Ein gemeinsames Vokabular funktioniert nur, wenn es auch wirklich geteilt wird. Wenn ein Teammitglied auf ein Problem stößt, hilft es nur, wenn beide Seiten dieselbe Sprache sprechen, und eine Gilde sorgt dafür, dass diese Sprache die gesamte Organisation erreicht.

Diese Seite teilen