Interview mit der Softwareentwicklerin und Trainerin Nicole Rauch

Consumer-Driven Contract Testing weiter gedacht
Keine Kommentare

Verteilte Systeme und Microservices gewinnen immer mehr an Bedeutung. Dies bedeutet, dass es eine wachsende Nachfrage gibt, automatisch und zuverlässig sicherzustellen, dass diese modularen Systeme auch gut zusammenspielen. Der derzeit führende Ansatz zum Testen der APIs zwischen Komponenten ist das Consumer-Driven Contract Testing (CDCT). Trotz seiner unbestreitbaren Verbesserungen gegenüber naiven Integrationstests weist es immer noch einige Schwächen auf.

Auf der diesjährigen APICON zeigte die Softwareentwicklerin und Trainerin Nicole Rauch die Schwächen von verteilten Systemen auf und stellte praktikable Ansätze vor, die über das übliche Consumer-Driven Contract Testing hinausgehen. Ein Grund für uns, noch einmal bei Nicole Rauch genauer nachzuhaken…

Entwickler.de: Der derzeit branchenführende Ansatz zum Testen der APIs zwischen Komponenten ist Consumer-Driven Contract Testing (CDCT). Was sind dessen Vorteile im Vergleich mit naiven Integrationstests?

Nicole Rauch: Mit CDCT ist man in der Lage, Änderungen an der zu testenden Backend-API sofort ins Frontend zu kommunizieren und so Frontend und Backend synchron zu halten. Das ist ein Riesenfortschritt im Vergleich zu den bisherigen Ansätzen, bei denen entweder das Frontend auf das Backend warten musste oder bei dem die Gefahr bestand, dass Frontend und Backend auseinanderdriften, was die Benutzung der API angeht.

Entwickler.de: Du sagst allerdings auch, dass Consumer-Driven Contract Testing einige gravierende Schwächen hat. Welche sind es?

Nicole Rauch: Eine große Schwäche liegt im Umgang mit dem Zustand des Backends. Bei GET-Requests brauche ich ja Daten im Backend, die ich in dem Request ans Frontend liefere. Woher kommen diese Daten? Normalerweise muss ich sie in meinem CDC-Test selbst herstellen, zum Beispiel durch Injizieren in die Datenbank. Damit laufe ich sofort Gefahr, dass diese Daten nicht den echten Daten entsprechen, sei es von der Struktur oder vom Inhalt her. Das kann soweit gehen, dass mein Test dadurch wertlos wird, weil ich eine Situation teste, die im Realbetrieb niemals vorkommt, und ich dafür Tests nicht durchführe, die relevant wären. Es ist sehr schwer, diese Test-Defekte zu erkennen.

Auch der Wartungsaspekt ist bei CDCT nicht zu vernachlässigen. Wenn man mal hunderte von Contracts geschrieben hat, dann ist es nicht so einfach, den Überblick zu behalten.

Bei POST- oder DELETE-Requests sehe ich noch weniger von dem, was im Server abläuft nach dem Übermitteln meines Requests. In CDCT schaue ich ja nur auf die Response. Bei einem POST-Request bekomme ich vielleicht den Status 200 und die Nachricht „OK“ zurück. Aber was bedeutet das genau? „OK – ich habe die Daten verarbeitet“ oder „OK – ich habe die Daten weggeworfen“? Das kann ich nur mit CDCT nicht erkennen. Dafür brauche ich zusätzliche Tests für das Backend, die dann wiederum Gefahr laufen, sich von der mit CDCT getesteten API zu entfernen.

Auch der Wartungsaspekt ist bei CDCT nicht zu vernachlässigen. Wenn man mal hunderte von Contracts geschrieben hat, dann ist es nicht so einfach, den Überblick zu behalten. Man kann natürlich Coverage Tools verwenden, um einen Überblick über die abgedeckten Teile der APIs zu bekommen, aber es bleibt mühsam.

Entwickler.de: Was gibt es noch für Ansätze? Du plädierst für einen Domain-driven Design und Modelling-Ansatz. Kannst Du noch einmal kurz zusammenfassen, was Du damit meinst?

Nicole Rauch: Der von mir vorgestellte Ansatz bedient sich einer ganzen Reihe von altbewährten Techniken. Im Wesentlichen geht es darum, eine sogenannte „Functional Essence“ bereitzustellen, das ist im Prinzip ein Mini-Backend, das die Kernfunktionalitäten des produktiven Backend-Servers implementiert. Man könnte diese Functional Essence auch Fake-Server, Rapid Prototype oder Modell nennen. Dieses Mini-Backend sollte man schnell hochziehen können, weil es sich wirklich nur auf die funktionalen Aspekte des Backends beschränkt und alle nichtfunktionalen Aspekte wie Performance, Persistenz, Security etc. weglässt. Wir können also simple Datenstrukturen verwenden, z. B. Listen, und einfache Algorithmen, z. B. einen Sortieralgorithmus aus einer Standardbibliothek. Das hilft uns bei der schnellen Umsetzung.

Wir sind ja gestartet mit der Idee des Testens der API im Zusammenhang mit Backend-State. Hier lässt sich die Functional Essence folgendermaßen einsetzen: Wenn man die Functional Essence quasi als Backend-Spezifikation betrachtet, dann kann man sie benutzen, um das Verhalten des echten Backends zu prüfen. Dazu kann man beliebige Sequenzen von API-Aufrufen parallel auf die Functional Essence und auf das produktive Backend loslassen. Danach kann man den Zustand der beiden miteinander vergleichen. Wenn alle API-relevanten Daten übereinstimmen, kann man davon ausgehen, dass die beiden gleich funktionieren. Wenn nicht, bekommt man gleich eine Liste von API-Aufrufen mitgeliefert, mit deren Hilfe sich das abweichende Verhalten reproduzieren lässt. Diese Vorgehensweise ist übrigens bei QuickCheck bzw. Property-Based Testing abgeschaut.

Aber damit hört die Nützlichkeit der Functional Essence noch nicht auf: Das Frontend kann sie benutzen, um schon in einer frühen Phase der Entwicklung auf echte Produktivdaten zugreifen zu können. Sie stellt also quasi einen intelligenten Mock für das Frontend dar.

Man kann sie auch unter dem Gesichtspunkt des Domain-Driven Design verwenden, um Funktionalitäten schnell auszuprobieren und gemeinsam mit den Domänenexperten zu betrachten. So können alle Projektbeteiligten sich leicht miteinander verständigen, Missverständnisse sehr früh erkennen und aus dem Weg räumen.

Entwickler.de: Frameworks wie Pact bieten eine Erleichterung, um ein Test-Framework nicht selbst erstellen zu müssen. Wie sind Deine Erfahrungen damit und was gibt es noch für empfehlenswerte Tools?

Nicole Rauch: Neben Pact, das es ja für einige Programmiersprachen gibt, kenne ich noch das SCC-Tool, das eine schöne Integration in Spring bietet. Wer also in diesem Technologiestack unterwegs ist, sollte mal einen Blick darauf werfen.

Entwickler.de: Du bist eine begeisterte Softwarenentwicklerin und als Softwareentwicklungscoach tätig. Wie ist nach Deiner Beobachtung der Wissenstand rund um Consumer-Driven Contract Testing und weiteren Testverfahren im Umgang mit Microservices?

Nicole Rauch: Da gibt es wirklich alles, angefangen von Teams, die gar nicht testen (und die auch sonst entsprechend schlecht testbaren und wartbaren Code schreiben) bis hin zu Teams, die es wirklich verstanden haben und mit der ganzen Bandbreite von Tests unterwegs sind und die natürlich auch CDCT einsetzen. Und dann natürlich alles dazwischen.

Unter uns gesagt, bin ich ja ganz froh, dass es auch noch Teams gibt, die näher an ersten Kategorie dran sind: So werde ich wenigstens nicht so schnell arbeitslos 😉

Vielen Dank für das Interview!

Nicole Rauch ist freiberufliche Softwareentwicklerin und Softwareentwicklungscoach mit umfangreichem Hintergrund im Compilerbau und formalen Verifikationsmethoden. Neben Specification by Example, Domain-driven Design, React.js/Redux, Node.js und der Sanierung von Java-Legacy-Code-Applikationen erobern sich funktionale Programmiersprachen, allen voran Haskell, langsam aber sicher einen festen Platz in ihrem Repertoire. Des Weiteren wirkte sie an der Ausrichtung mehrerer selbstorganisierter Konferenzen und an der Initiierung der Softwerkskammer, einer deutschsprachigen Usercommunity zum Thema Software Craftsmanship, sowie ihrer Karlsruher Regionalgruppe mit.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -