Deep Dive 133 –
End-to-End Testing mit Raphael Knecht
19.10.2023
- // Podcast
- // Deep Dive 133
Shownotes
In dieser Ausgabe haben Fabi und Jan im Studio Besuch von Raphael Knecht. Raphael ist Entwickler bei funk und werkelt dort an der Videolandschaft und Content Delivery.
Zusammen mit Raphael sprechen wir über End-to-End-Testing und wie es ihm und seinem Team die tägliche Arbeit erleichtert. Raphael berichtet, wie sein Team Akzeptanztests nutzt, um seine Microservice-Landschaft nicht nur stetig weiterzuentwickeln, sondern auch zu dokumentieren. Es geht um Fallstricke und die Herausforderung, trotzdem agil zu bleiben.
Mit End-to-End-Tests sollen Systeme aus Anwendungssicht ganzheitlich gecheckt werden können. Dabei werden möglichst produktionsnahe Umgebungen genutzt, um Szenarien von Input bis Output automatisiert zu überprüfen.
/transkript/programmierbar/deep-dive-133-end-to-end-testing-mit-raphael-knecht
Hallo und herzlich willkommen zu einer weiteren Folge der Programmierbar. Wir sind mal wieder mit einem Deep Dive für euch am Start und heute unterhalten wir uns über End to End Testing. Ich bin der Fabi und neben mir sitzt der liebe Jan. Hi Jan. Hallo. Falls ihr es noch nicht mitbekommen habt, hört noch die letzte Newsfolge nach. Der Jan ist unser neuer Programmierbar Community Lead und den hört ihr jetzt öfter hier im Podcast. Und neben dem Jan haben wir noch jemand weiteren Neuen und zwar jemand, der sich mit uns über End to End Testing unterhält. Und das ist der liebe Raffael. Hi Raffael. Ja, hallo.
Vielen Dank, dass ich heute hier sein darf.
Schön, dass du da bist. Du warst schon bei uns im Meetup. Du bist Entwickler bei Funk. Das, wie nennt man das?
Das ist das Medien...
Das ist das Content Netzwerk für junge Leute.
Von ARD und ZDF. Ich bin viel auf YouTube unterwegs, da kommt mir das das ein oder andere Mal entgegen. Von daher war ich mit deinen Beispielen, die du im Meetup gezeigt hast, so von den Content Beispielen, alles schon mal über den Weg gelaufen. Genau. Und wir unterhalten uns heute mit dir über End-to-End-Testing und so ein bisschen auch den Erfahrungsbericht. Wie macht ihr das bei Funk? Und weil es ja durchaus etwas ist, was ihr viel einsetzt und wie ihr das Ganze einfach nutzt. Vielleicht so für die Leute, die vielleicht mit Testing noch nicht so viel am Hut haben oder auf der Testing Pyramide irgendwo bei Unit Tests stehen, so kannst du probieren mal kurz zusammenzufassen in deinen Worten, was End to end Tests sind.
Also End to end Tests sind einfach vom Scope her viel größer als ein Unit Test. Ein End to end Test soll wirklich mehr oder weniger sagen Okay, mein System verhält sich im Ganzen so wie ich es erwarte. Das heißt, ich teste nicht einzelne Komponenten, sondern bin wirklich auf einem Level, wo ich sage Okay, wenn jetzt alle Microservices zusammenspielen und vorne wird das eingegeben, dann wirft das System hinten das raus. Und das ist das, was einem halt auch die Sicherheit gibt, dass das System so funktioniert, wie man es möchte und einem eine viel bessere Sicherheit gibt als vielleicht ein Unit Test, der nur sagt, dass kleine Komponenten so funktionieren, wie man es erwartet.
Und ist es denn was, also End-to-End-Testing, habt ihr das von vornherein bei Funk gemacht oder wie seid ihr überhaupt dahin gekommen? Weil ich würde jetzt mal sagen, so in der breiten Masse wahrscheinlich die End-to-End Tests. Deswegen habe ich es auch gerade noch mal erklären lassen, dass ihr nicht unbedingt die Tests, die ihr von vornherein so ein bisschen macht. Wie kamt ihr dahin, End-to-End Tests zu schreiben? Oder war das für euch von vornherein klar, dass ihr das tut?
Also wir sind alle sehr Testing affin in unserem Team. Das heißt, für uns sind Tests und auch die verschiedenen Ebenen von Tests von Anfang an wichtig gewesen. Und wir haben eben auch gerade durch unsere Anforderungen, dass wir ein kleines Team sind, dass wir viele kleinere Produkte haben, eben sehr früh festgestellt, dass wir Probleme kriegen, wenn wir nicht sehr gut zu Ende testen. Weil so die Standardanwendungsfälle, man programmiert ein Produkt, was man danach vielleicht nicht täglich wieder anpasst, was man nicht täglich weiterentwickelt, muss man trotzdem warten, muss man Versionen hochziehen, muss man Anpassungen machen. Und da helfen uns die Tests halt wirklich, dass wir sicherstellen, dass unsere Software Komponenten so zusammenspielen, wie wir es erwarten und geben uns da eben die Sicherheit. Und das haben wir schon sehr früh festgestellt, dass wir das brauchen. Gerade wenn wir unseren Code bearbeiten wollen, wenn wir agil sein wollen, wenn wir kurzfristig Änderungen umsetzen wollen, dann haben wir für uns festgestellt, hilft uns sehr, sehr gut.
Um da mal ein bisschen Kontext zu setzen, ohne jetzt zu sehr ins Detail zu gehen. Aber was ist denn das Produkt, an dem ihr arbeitet? Und warum ist es vielleicht zu schwer oder zu komplex konventionell zu testen?
Also wir haben mehr oder wenigerwir haben am Anfang Monolithen mittlerweile sehr viele Microservices, die mehr oder weniger, also unsere Landschaft ist die Videolandchaft. Das heißt, wir haben Leute, die erstellen Videos für Funk, die laden die irgendwo hoch und unsere Softwarekomponenten sollen sicherstellen, dass sie dann in den Mediatheken erscheinen, dass sie auf der eigenen Website erscheinen, dass Untertitel rechtzeitig beantragt werden. Das ist so die Aufgabe, die unsere Komponenten erfüllen sollen. Und so ist es eben das, was wir sicherstellen wollen. Das heißt, wir haben auch Clients, die nicht so häufig frequentiert werden. Das heißt vielleicht auch Fehler fallen nicht direkt auf. Nichtsdestotrotz sind Fehler hier und da dann doch sehr kritisch. Das heißt, das ist auch das Setup, dass wir sagen Okay, wir sind ein kleines Team, wir wollen viele Clients bedienen wollen, wir wollen stetig weiterentwickeln können, ohne viel Zeit für Wartung oder Fehlersuche zu verlieren. Und das ist so das Setup, weswegen wir letztlich sehr stark dann auch zu Ende zu Ende Tests gegangen sind.
Und wenn du sprichst von viele Clients bedienen wollen, heißt dann Clients in dem Fall auch sind es ihr. Also du hast gemeint, man lädt beispielsweise. Ich habe ja vorhin gemeint, ich habe sehe einige Videos auf YouTube von Funk. Das heißt, ihr habt irgendwo einen CMS, wo man das Video hochlädt. Eure Services verarbeiten die dann und schicken sie dann an, sind dann Clients so was wie YouTube.
Oder so? Genau, unsere Clients ist so was wie die ARD Mediathek, die ZDF Mediathek. Wir archivieren die Videos, damit andere Rundfunkanstalten darauf zugreifen können. Wir bestellen rechtzeitig Untertitel, damit unsere Videos barrierefrei zur Verfügung stehen. Und so haben wir sehr viele Clients wie Mediatheken, Untertiteldienstleister, Archivierungssysteme und die möchten wir alle bedienen. Allerdings ist es so, dass gerade.
Wie gesagt, dadurch, dass wir viele.
Kleine Clients haben, die wir auch nicht ständig weiterentwickeln, sondern die eigentlich auch dann eher in so einen Wartungszustand übergehen, wir trotzdem sicherstellen müssen, dass wenn wir unser System aktualisieren, weil wir eine Version hochziehen, weil wir kleinere Anpassungen machen, dass eben nichts schief geht. Das heißt, das ist für mich ein Setup, wo ich sage, da machen Ende-zu-Ende Tests Sinn, weil ich eben kleine Änderungen deployen kann und weiß okay, meine wesentlichen Business Cases, die funktionieren immer. Das heißt, der Standard Case, jemand lädt ein Video hoch. Ich erwarte, dass unser System dafür sorgt, dass es in den Mediatheken verfügbar ist. Da wird eben bei jedem Build und Deployment überprüft. Und damit stellen wir sicher, dass unser System funktioniert.
Und wenn ihr, sagen wir mal, oder vielleicht noch eine vorab bei der kleinen Frage waren. Glaubst du denn, dass es bei euch ein spezieller Fall ist, dass ihr viele Clients, also ist es wichtiger, weil ihr viele externe Clients habt, auf die ihr keinen Einfluss habt, Ende-zu-Ende-Tests zu schreiben? Oder wäre es genauso wichtig für jemand, der, sagen wir mal, ein Self-Contain System schreibt, wo er Full-Stack Frontend und Backend sich drum kümmert und es eigentlich keine großen externen Abhängigkeiten gibt, außer der eigens entwickelte Code so? Wäre das ein anderer Fall so? Oder würdest du sagen, Ende-zu-Ende-Test kommt nicht auf das Produkt an und auch nicht irgendwie auf die Größe an?
Ich würde schon sagen, gerade auch der Umfang kommt auf das Produkt an. Also wenn ich jetzt zum Beispiel, wir haben auch ein kleines eigenes Monitoring Frontend, das würden wir jetzt nicht Ende-zu-Ende testen, da sagen wir, die Tests sind sehr aufwendig. Wenn da ein Fehler drin ist, dann merken wir das selbst, da sind wir selbst die Clients, da ist der Schmerz nicht so groß. Also ich denke, es hängt schon wesentlich vom Produkt ab. Und gerade dieser Fall, okay, man hat viele kleinere Systeme, die eher in so einem Wartungszustand sind, ist für mich ein guter Grund zu sagen, okay, wir wollen da wirklich durch Ende-zu-Ende Tests diesen Wartungsaufwand maßgeblich reduzieren. Ich glaube, wenn man eher eine kompakte Applikation hat, vielleicht auch mit ein, zwei starken Fachlichkeiten, dann ist es nicht ganz so ein großes Thema, da man vielleicht auch als Entwickler über alle Stellen im Code immer mal wieder drüber kommt. Aber gerade wenn man in Richtung sehr kleine Details geht, die.
Gefühlt auch.
Dann fehleranfällig sind, weil sie sich in kleinen Details unterscheiden, da denke ich, da macht ein Ende-zu-Ende-Test besonders Sinn, weil man eben wirklich nur durch eine gute Testabdeckung aus meiner Sicht das schafft, auch langfristig irgendwie performant zu sein. Also wenn ich mit fünf kleinen Clients irgendwie jede Woche einen Fehler in jedem Client suche, dann blockiert mich das ganz anders, als wenn ich vielleicht irgendwie in einer Fachlichkeit, in der ich eh, sage ich mal, fünf Tage die Woche arbeite, was suchen muss, wo ich mich auch gut auskenne.
Jetzt hast du ja eben schon diesen Trade-off angesprochen zwischen End-to-End Tests sind relativ teuer in Anführungszeichen. Du kannst oder willst nicht alles testen. Manches ist auch zu komplex zu testen. Und gleichzeitig bieten sich ja End-to-End Tests dafür an, dass man auch mit nicht technischen Leuten drüber sprechen kann. Wie entscheidet ihr bei euch in welcher Runde, was ihr testen wollt, was euer happy path ist, was wichtig genug ist, wo sich dieser Trade-off eben auch lohnt? Macht ihr das in dem Entwicklungsteam zusammen? Habt ihr Product Owner, habt ihr Projektmanager? Sind da nicht technische Menschen mit dabei oder sprecht ihr das alles intern ab?
Wir haben kaum nicht technische Menschen. Wir sind wirklich drei bis vier Entwickler, die, sage ich mal, unsere Produkte weiterentwickeln. Und tatsächlich ist es so, dass wir eigentlich relativ wenig absprechen aktiv. Also viel ist halt wirklich Kultur auch in unserem Team, dass man weiß, okay, das und das ist unsere Erwartung an uns gegenseitig, dass wir das testen. Natürlich testet der eine vielleicht in einem Fall ein bisschen detaillierter als der andere dann auf Ende zu Ende Testebene.
Aber so viel Absprache.
Ist da tatsächlich nicht, weil wir gefühlt mittlerweile eine sehr gute Kultur im Team haben, sehr einheitlich und alle auch ein gutes Verständnis haben, was Ende zu Ende getestet wird und was nicht. Und gerade so neue Features oder so, die werden in der Regel Ende zu Ende getestet. Also da probieren wir dann auch quasi Testgetrieben auf einer höheren Ebene zu arbeiten, dass wir sagen Okay, auch da probieren wir eben zeitnah oder im besten Fall davor eben den Ende zu Ende Test zu schreiben, bevor wir dann das Feature implementieren.
Und den Ende zu Ende Test, weil du ja also beim neuen Feature wird es ja nicht sein, okay, es gibt den einen... Also kannst du mal... Hast du irgendein Beispiel für irgendein Feature, was ist das erste, was du bei einem Feature hast zu schreiben? Weil das fangt ja immer mit Ende-zu-Ende-Tests an und reichert sie mit Unit-Tests an? Falls ja, macht ihr Happy Paths als auch irgendwie den Fehlerfall? Oder wie probierst du es uns mal an einem neuen Feature zu erklären, so wie du, wie du, bisschen, wenn wir jetzt nicht, der neue Mitarbeiter, so der jetzt eure Kultur noch nicht drin hat, so und sagt, ich mache jetzt hier das neue Feature, so was würdest du jetzt.
Wie machst du das? Genau, so, häufig ist es so, wir haben.
Zum Beispiel jetzt, als wir die ARD neu eingebunden haben, also unsere Videos quasi auch in die ARD Mediathek gespielt haben.
Ist es so, dass wir.
Schon nicht unbedingt als erstes eine Akzeptanz schreiben, aber zuvor wir live gehen, auf jeden Fall quasi den Happy Path. Das ist häufig das erste so. Ich definiere, wie das Video in unserem CMS aussieht. Also wenn das CMS Video den Titel hat und die Beschreibung und die Tags und den Creator und so weiter, dann erwarte ich, dass in der ARD genau die Informationen vorliegen. Also dass wir wirklich einmal sagen okay, so ein maximal gefülltes Video, das betrachten wir jetzt. Und da haben wir die Erwartung, okay, wenn das mit den ganzen Informationen im CMS hochgeladen wird, dann wird es mit den Informationen an die ARD ausgespielt. Das ist häufig so der erste Test.
Okay, und das heißt, das erste, was wir wirklich machen, ist auch Ende-zu-Ende-Test. Und du hast jetzt gerade den Begriff Akzeptanztest dafür gewählt. So vielleicht irgendwie wie, was ist denn jetzt ein Ende-zu-Ende-Test oder ein Akzeptanztest? Aber zumindest schon mal die erste -wir können ja gleich dann noch mal weitergehen in dem Entwicklungsphase -aber das erste, was ihr macht, ist wirklich so ein Ende-zu-Ende oder Akzeptanztest zu schreiben. Das ist das erste, was ihr macht.
Ja, erst mal danke, dass du mich darauf aufmerksam gemacht hast. Tatsächlich ist es bei mir in der Arbeit so, dass wir die sehr häufig äquivalent verwenden. Ende-zu-ende-test und Akzeptanztest. Das ist nicht das Gleiche. Ende-zu-ende beschreibt mehr oder weniger den Scope des Tests und das heißt bei uns Ende zu Ende, weil er eben Microservice übergreifend ist. Das heißt, wir haben den CMS Importer Microservice, wir haben den ARD Microservice, wir haben dazwischen eine Datenbank und ein Queueing System und Ende zu Ende Test heißt bei mir oder bei uns, wir testen unser System eben nicht den einzelnen Microservice, sondern wirklich dieses Systemzusammenspiel aus den Microservices, die relevant sind. Das heißt Ende zu Ende beschreibt sehr genau den Scope dessen, was wir testen. Und Akzeptanztest.
Ist eher so die.
Abstraktion, das Abstraktionslevel, auf dem wir das beschreiben. Das heißt, wir verwenden Cucumber. Das ist ein Framework, was es ermöglicht, das Ganze so ein bisschen in eine bessere Sprache zu bringen oder in eine allgemein verständlichere Sprache. Und dass wir weggehen von so einer technischen Sprache wie wenn der an der Endpunkt das und das zurückgibt oder wenn die und die Notification an den Endpunkt geschickt wird. Das ist eher eine technische Sprache. Und Akzeptanztest heißt einfach, dass man auf ein Abstraktionslevel geht, was es eher aus Nutzer Sicht beschreibt. Und unsere Tests fangen in der Regel so an, oder es ist gegebeneben, dass jemand ein Video in CMS hochlädt. Das ist so die Sprache, sag ich mal, die allgemein verständlicher ist und wo dann eben abgekapselt ist, was da hinten dran genau dann für technische Implikationen angenommen werden. Aber der erste Schritt ist quasi immer okay, wir schreiben, wenn jemand das hochlädt, dann erwarten wir, dass das und das passiert.
Und wieso macht ihr auf dieser sprachlichen Ebene diese Abstraktion? Also wenn ihr sagt, ihr habt ein sehr technisches Team, dann könnte man ja annehmen, dass auch alle Beteiligten das eigentlich ein oder zwei Level tiefer auch verstehen würden. Was versprecht ihr euch davon, das auf so eine Meta-Ebene, auf so eine menschlichere Sprache zu heben?
Der erste große Punkt ist Dokumentation. Also wir dokumentieren wenig jenseits von Code. Das heißt auch Akzeptanztests sind quasi unsere primäre Stelle, wo wir dokumentieren, wo wir tatsächlich auch mal mit nicht technischen Ansprechpartnern drauf schauen. Also wenn jetzt jemand fragt okay, wie werden denn die Felder gemappt oder so oder was muss ich da eingeben, damit das Feld da hinten so erscheint? Dann ist es durchaus was, was man auch in einem Akzeptanztest einfach nachschauen kann. Jemand anderes schaut vielleicht irgendwie in den Wiki oder so. Wir gucken in den Akzeptanztest, da steht dann okay, wenn das Feld so und so im CMS heißt, dann wird es auf das und das unten gemappt. Okay, also das ist durchaus auch ein Kommunikationsmittel mit anderen Leuten, die jetzt vielleicht einfach nur eine fachliche Anfrage haben und ist in erster Linie eben auch unsere Dokumentation.
Und das Tolle da ist halt.
Dass die Dokumentation lebt. Das heißt, vielleicht kennt man es aus einem eigenen Projekt oder so, man schreibt eine Dokumentation im Wiki und entwickelt den Service immer weiter und irgendwann passt die Doku nicht mehr zum Service oder umgekehrt.
Und der große.
Vorteil ist halt eben wirklich bei den, ich sage jetzt bewusst, Akzeptanztests, die dann diesen Ende-zu-Ende-Scope haben, dass man eben diese Gefahr nicht hat. In dem Moment, wo das System sich anders verhält, als unsere Dokumentation, also unsere Tests, wenn die Tests rot und man sieht direkt okay, entweder das System verhält sich nicht so wie die Anforderung ist oder Anforderung ist nicht mehr so wie das System das aktuell abbildet.
Und wenn wir jetzt aber vielleicht noch mal, es auf der technischen Ebene zu sein, du die Anwendungsfälle, die du beschrieben hast, vielleicht auch ein bisschen zu verstehen, dass du hast gesagt, ihr kümmert euch jetzt dann darum, im CMS werden Dinge angelegt und landen dann bei den einzelnen Clients bzw. Plattformen. Das heißt, wenn wir hier einen End-to-End Test beschreiben, dann reden wir nicht von einem Frontend, sondern wir reden bei euch von einem Backend Service komplett, das ist eine Microservice Architektur. Das heißt, der die... Vielleicht kannst du uns, können wir gleich mal darauf eingehen, damit ich so was testen kann, braucht es ja bestimmte Komponenten. Aber sowas, der Einstiegspfad für so einen Ende-zu-Ende Test ist dann trotzdem immer irgendwie ein Restendpunkt oder sowas? Oder was ist so, womit beginnt ein Ende zu Ende Test.
Bei euch? Genau. Also wir testen unsere eigenen Services Ende zu Ende. Das heißt jeden Code, den wir selbst schreiben. Das soll uns gerade auch die Sicherheit geben, dass wenn wir was an unserem Code ändern, sich nach außen alles noch so verhält, wie es bisher ist. Und unser CMS, was du ja gerade gesagt hast, was dann irgendwie auch eher was ist mit Restend Punkten, was irgendwie mit unseren Backend.
Systemen spricht.
Das wird bei uns dann, das heißt weg gemockt oder weg gestappt. Das heißt, da simulieren wir quasi eins zu eins das Verhalten, wie wir es aktuell aus unserem produktiven CMS kennen. Das heißt, wir kennen aus dem produktiven CMS okay, wenn da jemand ein Video hochlädt, dann schickt das CMS zum einen eine Nachricht, also ruft bei uns einen REST-Endpunkt auf, sagt hier das Video ist jetzt neu und zum anderen sind die Schnittstellen von dem CMS, also die API Endpunkte, verhalten sich natürlich auch anders. Wenn da neues Video dazukommt, dann gibt es unter einem Pfad entsprechend das Video abzuholen mit allen Informationen. Und genau so verhält sich auch unser gefaktes, sag ich jetzt mal, CMS in unserem Test. Das heißt, wenn wir so was schreiben wie es gibt ein Video, dann tun wir so, dass unser CMS, mit dem wir im Test arbeiten, sich genauso verhält wie das Produktiv-CMS, wenn ich da jetzt ein Video anlege.
Also wirklich eine Form von Fake, also dem könnt ihr sagen: „Hey, du hast jetzt dieses Video, hat eine kleine interne Memory Datenbank und weiß dann, ich habe das und kann es beim nächsten Endpunkt zurückgeben.
Genau. Wir verwenden an einer Stelle zum Beispiel Wire Mock. Das ist einfach ein Programm, sag ich mal, wo man sehr leicht konfigurieren kann, was unter welchen Endpunkten zurückgegeben wird. Und dann verhalten wir uns eben so, also verhält sich der Wire Mock so wie das echte System. Und wenn wir sagen, es gibt ein Video, dann ist unter irgendeiner API URL jetzt ein Video verfügbar mit den Metadaten, wie wir es vom Produktiven kennen.
Und der Ende zu Ende Test beginnt jetzt aber nicht im Frontend des CMS, weil das CMS kein Produkt von euch ist oder weil es ein Standard Produkt ist?
Genau. Also das CMS, das liegt nicht in unserem Scope, liegt dementsprechend nicht in unserem Ende zu Ende Test.
Scope.
Und dementsprechend werden wir es weg, mocken wir es weg. Wir haben aber auch zum Beispiel selbst ein Frontend, was wir Ende zu Ende testen in einem gewissen Bereich und wo wir dann wirklich auch, sage ich mal, Tests schreiben mit einem Selenium Web-Driver, wo dann ein Formular ausgefüllt wird und wo dann an einem anderen Ende was abgeschnitten wird, nämlich am SMTP Server. Da sagen wir dann okay, wir testen unsere Produkte bis zum SMTP Server, aber den ersetzen wir durch einen Test-Doppel, sag ich jetzt mal, das ist der neutralste Begriff, wo wir einfach sagen können, okay, da können wir am Ende anschauen, wenn jemand vorne in Anführungsstrichen in das Webformular das und das eingegeben hat, dann sollte am Ende irgendwo eine Mail raus purzeln. Und da reden wir dann mit so einem gefakten SMTP Server, der uns sagt Okay, ich habe jetzt nicht wirklich eine Mail rausgeschickt, hätte aber jetzt die Mail mit dem Betreff an die.
Personen geschickt.
Um.
Nochmal auf die Frage zurückzukommen, was der Eingangspunkt ist. Dadurch, dass ihr ja schon eure ganze Anwendung testet, müsst ihr ja aber auch die ganze Anwendung haben. Also wo ich bei einem klassischen Unit Test sag ich mal 20 Zeilen Code brauche und die relativ isoliert ausführen kann, braucht ihr ja eure Anwendungen, Datenbanken, Webserver. Also ich weiß ja nicht, was alles dazugehört, aber auf alle Fälle schon mal ziemlich viel. Wie und wo baut ihr das zusammen und wo wird das dann alles ausgeführt?
Tatsächlich haben wir das mittlerweile alles. Also alle unsere Microservices haben eine eigene Pipeline, die Microservices bauen. Ich sage mal, da fällt am Ende.
Erst mal.
Ein Dschar.
Raus, dann ein Docker File.
Dann ein Docker Image. Und dann ist es so, dass wir für den.
Ende-zu-ende Test.
Wirklich in der Docker Umgebung, sage ich.
Mal, die Services.
Hochfahren, die wir brauchen. Das heißt, wir haben eine Docker Umgebung, in der läuft eine Datenbank, eine Queue, der CMS Importer und jetzt zum Beispiel mal der AD Service als Beispiel. Und dann hat man eben diese, ich sage mal, zwei Infrastruktur Komponenten und zwei Microservices von uns, die in der Docker Umgebung starten. Und gegen diese Docker Umgebung führen wir unsere Tests durch.
Das heißt, ihr habt pro Test auch schon so mit definiert, was ihr alles braucht, damit ihr nicht jedes Mal alle Microservices hochfahren müsst, sondern immer nur ein gewisses Subset sozusagen.
Genau. Also in der Regel fahren wir so, sage ich mal, zwischen drei und fünf, sechs Microservices hoch, damit so ein Ende zu Ende Test dann alles das abtestet, was alle Komponenten, sag ich mal, die.
Er benötigt.
Aber ist es auf Test Ebene definiert oder auf Service Ebene? Ich würde mir jetzt eher vorstellen, so ich habe den, ich sage jetzt mal den Subtitle Service und der weiß immer die Abhängigkeiten, wenn ich alle Ende zu Ende teste von Subtitle verwenden immer die gleichen Hochfahren oder definiert ihr es wirklich auf Test Ebene und ihr müsst euch überlegen was sind die Abhängigkeiten?
Also.
Rein technisch lösen wir es über Annotation. Das heißt wir schreiben.
Über jedes Feature File heißt.
Es, also indem fachliche Features beschrieben werden.
Schreiben wir drüber @requared services und dann geben wir da an, was da sein muss.
Damit unser System.
Wartet.
Dass dann auch alle hochgefallen sind, dass alle da sind.
Eine andere Variante wäre wahrscheinlich auch gewesen. In derfolder-Struktur eines Services sind alle Feature Cucumber Files entkapselt und wahrscheinlich brauche ich für einen Service immer die gleichen Abhängigkeiten, so ungefähr. Aber wahrscheinlich nicht für jeden Test jede Abhängigkeit. Von daher, okay, verstanden.
Wenn ihr also pro Test immer einige dieser Microservices hochfährt, dann ist das ja schon auch eine relativ komplexe.
Und auch.
Teure Art des Testens. Also teuer wirklich im Sinne von wie viel Hardware Leistung brauche ich in meiner Pipeline, das jetzt alles auch wirklich mal zu testen? Wie managet ihr das? Wie steuert ihr das aus, dass euch am Ende des Tages, ich sage mal ganz salopp nicht die Pipeline Kosten die Haare vom Kopf fressen.
Dass.
Ihr keine mehr ausführt, weil es zu lange dauert.
Ja, oder so was auch.
Tatsächlich ist es ja auch so, dass wir häufig abwägen müssen, wie nah ist man an Produktion, wie testbar will man sein? Um nur ein Beispiel zu nennen, gerade auch wenn wir unsere Systeme betrachten. Sachen, die Zeit kosten, sind häufig konfigurierbar. Das heißt, vielleicht in Produktion brauche ich irgendwie ein Delay zwischen zwei Steps.
Im Akzeptanztest halte ich den möglichst kurz, damit mein.
Test möglichst schnell ausgeführt wird.
Und tatsächlich ist es auch dann glaube ich eher eine Frage der Microservices. Also unsere Microservices sind wirklich Microservices.
In dem Sinne.
Sehr, sehr klein. Das heißt auch tatsächlich, dass jetzt selbst der Aufwand, sage ich mal, von fünf Microservices plus eine MongoDB plus eine Rappet MQ in Docker eigentlich noch mit einem.
Guten.
Zeitaufwand auch möglich ist. Also unsere Maschine, unser GitLab Runer, der die Tests ausführt, der ist jetzt.
Nicht überdimensioniert.
Und der schafft das eigentlich in einer ganz ordentlichen Zeit. Und ich glaube, das liegt in erster Linie daran, dass halt wirklich die.
Microservices klein sind.
Und zum anderen wir natürlich auch probieren, die Tests zum einen schnell zu halten, damit man sie eben auch gerne ausführt und zum anderen eben auch, wie schon gesagt, wenn die Tests lange dauern oder so, dann schreckt es natürlich auch ab, sie auszuführen. Das sind, glaube ich, so die die wichtigsten Punkte.
Das heißt, ihr habt aber auch einen eigenen Runer und nutzt nicht irgendwie GitLab Cloud Runer.
Oder sowas? Nein, genau. Wir haben eine eigene GitLab Instanz und haben auch einen.
Eigenen Runer.
Und.
Das heißt aber ihr führt sie nur in dem GitLab Runer aus oder macht ihr es auch, also werden alle End-to-End Tests auch noch lokal ausgeführt? Ist das so eine... Also unterhalten wir uns über Zeiten, die auch wirklich regelmäßig ausführen? Oder ist es so, dass ich deploye und dann ich habe meine eigenen End-to-End Tests ausgeführt und der Rest kriege ich notfalls ein Ping?
Also in der Entwicklung ist es natürlich auch möglich. Also ganz normal mit der ID, in der man arbeitet, sage ich mal, startet man zwei IDE's, startet da die Konfigs, die sind auch eingecheckt, also quasi, dass man auch lokal eins zu eins, sage ich mal, eine Akzeptanztestvariante unserer Applikation startet. Und das ist eigentlich.
Teil.
Des Entwicklungsprozesses. Es ist nicht so, dass das wirklich jetzt ewig dauert. Also vielleicht auch da so einfach ein bisschen die Angst nehmen, ich habe jetzt keine Zeit im Kopf, aber so einen Akzeptanz auszuführen, das dauert jetzt keine Ewigkeit bei uns.
Aber ich sehe, genau, ich glaube der einzelne, ich dachte nur, ob man die gesamte Suite sozusagen am Ende von einem Feature, also ist das was, was ich lokal noch ausführe oder.
Eben nicht? Also die komplette, alle alle Tests, sage ich mal, führt man nicht aus. Tatsächlich ist es ja so, dass wir viele Microservices haben. Viele haben dann quasi ihre eigenen fachlichen Akzeptanz Tests. Das heißt, die sind natürlich auch geschnitten. Ist nicht einmal alle Akzeptanztests, sondern ist dann für jeden Service quasi die eigenen Akzeptanztests. Und wenn ich jetzt eine Entwicklung an einem AAD Part mache, dann würde ich schon, sage ich mal, die Akzeptanztests für den AAD Service jederzeit ausführen. Aber die Wahrscheinlichkeit, dass ich jetzt mit meiner Änderung im AD Microservice was für die ZDF Logik kaputt mache, die ist sehr, sehr gering. Das heißt, da.
Würde ich mich dann auf.
Die Pipeline laufen, die quasi am Ende einmal sagt Okay, ich für für dieses.
Setup von Versionen, also dass wir dann sagen Okay.
Am Ende wollen wir die Version vom CMS Importer mit der Version.
Vom AD Service, mit der Version.
Vom ZDF.
Service deployen.
Bevor wir das machen, führen wir quasi für dieses Setup.
Also für dieses Set an Versionen.
Einmal die komplette Qualitätssicherung durch. Das heißt, da laufen dann alle Tests gegen diese neue Umgebung, die wir als nächstes deployen wollen.
Das heißt aber wirklich dann eigentlich nur daher, dass das unnötig ist und nicht weil es zu lang dauern würde. Das ist nicht der Punkt, dass man sagt, ich mache nicht einfach alle, weil es zu lange dauert, sondern weil die Wahrscheinlichkeit sehr gering ist und ich mir die wenige Zeit trotzdem sparen kann, so.
Alle auszuführen. Genau, es wäre aufwendiger, irgendwie die Server so hochzufahren, glaube ich, als jetzt das auszuführen. Und wir sind jetzt bei unserer Pipeline, die jetzt wirklich auch nicht auf dem stärksten GitLab Rana läuft, sage ich mal bei so circa 15 Minuten für eine, 10 bis 15 Minuten für eine Test Suite, Ende-zu-Ende Test Suite für einen Microservice, könnte man jetzt parallelisieren, sage ich mal.
Dass.
Denn der ganze Step in 20 Minuten abläuft, aber.
Anders.
Sind wir bei knapp einer Stunde oder so. Also dass wir wirklich, sage ich mal, immer so zwischen.
Vielleicht acht und doch dann.
15 Minuten sind pro Microservice mit seinen Akzeptanztests.
Was ja auf jeden Fall schon dann wahrscheinlich zu lang wäre für ich führe es lokal alles irgendwie aus, selbst wenn ich am Ende von einem Feature das einmal mache. Und okay, jetzt haben wir den Part irgendwie mit Ressourcen einerseits, sie auszuführen, so, aber es ist ja durchaus ein nicht geringer Aufwand, dahin zu kommen, überhaupt so eine Infrastruktur zu haben. Also gerade dieser Part mit so im Nachgang einführen, das ist, glaube ich, stelle ich mir durchaus schwierig vor. Ihr habt es ja wahrscheinlich direkt von vornherein gemacht, aber du hast ja schon gemeint, ihr habt sehr, sehr viele Clients, wo ich dann mal überlegen muss, okay, Fake ich jetzt hier, also brauche ich wirklich irgendwie eine Form von Implementierung? Habe ich hier einfach nur einen Mock und will sozusagen bei einem SMTP Client überprüfen, dass eine E-Mail auch verschickt wurde oder reicht mir ein Stap, der einfach immer nur Dummi Daten zurückgibt, mit dem ich sie vorher füttere? Dann gibt es noch viele andere Komplexitäten. Ich weiß nicht, ihr seid jetzt Microservices, auch vielleicht Kommunikation untereinander oder so. Also für uns mal dadurch, wie viel Komplexität ist es bei euch, so eine Infrastruktur aufzubauen und auch vielleicht Fehleranfälligkeit bei sowas?
Also Fehleranfälligkeit ist bei uns tatsächlich sehr, sehr klein. Also wir haben wenig Flackern in der Akzeptanz oder Ende zu Ende Tests. Das ist ja häufig etwas, was man liest. Häufig flackern die, sind mal grün, sind mal rot. Das haben wir tatsächlich fast gar nicht. Also wir haben eine sehr aussagekräftige Test. Entweder sie sind grün oder sie sind rot. Es ist auf jeden Fall aufwendig, das einmal aufzusetzen. Gerade auch bei unserer Microservice Landschaft. Also wir sind bei Monolithen gestartet, sind dann rüber gewechselt in eine Microservice Landschaft und hatten.
Anfangs.
Auch sehr stark mit Asynchronität zu kämpfen. Das heißt, wir haben natürlich einen Testfluss, der sagt, wenn das passiert, dann erwarte ich das und das. Auf der anderen Seite steht ein Programmfluss, der das Ganze verarbeiten muss. Das heißt, der Wenn-Schritt muss verarbeitet werden, der Dann-Schritt muss verarbeitet werden. Und ich möchte meine Annahmen, also meine Search natürlich erst ausführen, wenn das Programm das auch verarbeitet hat. Das ist bei uns eine große Aufgabe gewesen, dass wir tatsächlich eben häufig das Problem hatten, wenn man jetzt eine Queue dazwischen schaltet und vielleicht noch ein, zwei Requests von einem nachgelagerten Service.
Asynchrone Requests.
Abgeschickt werden, dass der Testfluss zu schnell für den Programmfluss ist. Das heißt, der Test erwartet, dass jetzt das Video in der ARD ist. Die Verarbeitung steckt aber noch mitten im ARD Service. Das heißt, das ist so ein Fall, wo wir tatsächlich auch viel Zeit investiert haben, dass wir gesagt haben, okay, wir nutzen jetzt eine Möglichkeit, die unsere Microservices zu monitoren. Das heißt, ein Microservice sagt Bescheid, wenn er was fertig verarbeitet hat, damit der Test entsprechend wartet und dann wirklich nicht irgendwie zu früh anfragt. Und das sind schon viele Herausforderungen, denen man begegnet. Also es ist nicht so, dass das Ende-zu-Ende-Tests die einfachsten Tests aus der Test-Pyramide sind, sondern dass man schon ein Invest tätigen muss, diese Sicherheit zu bekommen, die sie einem geben. Und ich glaube, da ist wirklich so dieses Commitment im Team ganz entscheidend, dass man nicht beim ersten Widerstand oder bei der ersten Komplexität sagt: Okay, dann testen wir es nicht oder es.
Ist nicht testbar, dann lassen wir es lieber, testen wir einen anderen Case.
Also ich glaube, da hat uns wirklich geholfen, dass wir einheitlich diese Meinung haben, okay, diese Tests haben für uns diesen hohen Wert, dass wir dieses Investment eingehen.
Jetzt hast du ja schon gesagt, es sind nicht die einfachsten Tests in der Test-Pyramide und ihr musstet da auch schon an der einen oder anderen Stelle eigene Logik einführen, ein paar von diesen Cases abzudecken. Wann ist denn der Punkt erreicht, wo du anfangen musst, Tests für deine Testlogik zu schreiben? Verstehst du, was ich meine? Sobald du jetzt so einen Helper hast, der guckt, ist dein Service fertig mit Bearbeitung? Hast du ja schon wieder neue Logik eingeführt, die ja eigentlich auch so ein bisschen getestet werden muss?
Ja, da sind wir tatsächlich so, dass wir eigentlich relativ wenig von dieser zusätzlichen Logik jetzt noch mal irgendwie Unit testen oder so. Das sind für uns wirklich Helfer, sage ich mal, dass wir sagen okay, wir brauchen da ein, zwei Erweiterungen, damit unsere Anwendung testbar sind. Genau bei denen gehen wir dann davon aus, dass eben über die Akzeptanz Test auch deren Funktion mit abgedeckt ist.
Du hast ja auch gerade schon die Testing Pyramide angesprochen und wenn du jetzt, wenn ihr jetzt Ende zu Ende Tests definiert, das erste ist, was ihr, was ihr tut in eurer Testing Strategie. Jetzt könnte man sich ja zurücklehnen und sagen Na gut, da ist ja definiert, dass das Ganze funktioniert. So die Interna. Wie es funktioniert, kann mir dann ja jetzt eigentlich egal sein. So die Unit Tests, ja gut, das ist ja über einen Akzeptanztest gemacht. Also was ich formuliere es jetzt mal nicht in der Aussage, sondern in der Frage: Welche Tests aus der Testing Pyramide macht ihr noch? Und aus welchen Gründen macht ihr sie?
Wir machen ganz viele Tests und auch ganz viele verschiedene Tests, weil jede ihre Berechtigung haben. Und das Ziel von einem Akzeptanz-oder Ende-zu-Ende-Test ist es nicht, ein kleines Detail zu testen. Das ist vielleicht dann eher die Aufgabe des Unit Tests, dass ein Unit Test wirklich dann.
Schaut.
Dass ja wirklich einen Set an Tests, den man auf der Abstraktionsebene von einem Ende-zu-Ende-Test nicht schreiben will, den schreibt man auf einer Unit-Test-Ebene. Was weiß ich, ein Taschenrechner 1+1 ist 2 und 2+1 ist 3 und so weiter. Da würde man nicht für jeden für jeden Case einen Akzeptanztest schreiben. Man muss immer Kosten und Nutzen abwägen. Die Kosten bei einem Akzeptanz-oder Ende-zu-Ende-Test sind groß. Der dauert einige Sekunden. Ein Unit Test dauert einige Millisekunden. Das heißt, da muss man wirklich schauen: Was möchte ich in welchem Detailgrad auf welcher Stufe abtesten? Und auf die Frage, was wir einsetzen. Wir machen Unit Tests für die meisten unserer Klassen, also eher Klassen basiert, dass wir da eins zu eins fast eine Unit Test schreiben. Wir machen was, wir machen Contract Tests, die für uns wichtig sind, weil die wirklich die Kommunikation über die Datenbank und über die Queue sicherstellen. Das heißt, dass eine Message, die von einem Service in der Datenbank geschrieben wird, von einem anderen auch gelesen werden kann, genauso bei einer Queue. Und auch so etwas wie Regressionstest, dass wir sagen okay, wir haben eine nicht-relationale Datenbank, das heißt, wir haben auch veraltete Elemente drin, die vielleicht nicht alle Felder haben, die neue haben, dass wir dann sagen okay, wir wollen auch sicherstellen, dass eine alte Version, die noch in der Produktiv-Datenbank liegen kann, jederzeit gelesen werden kann.
Also da haben wir wirklich verschiedene Tests, die eben verschiedene Anforderungen abdecken. Und die Ende-zu-Ende Tests haben da die Verantwortung, dass wir wissen okay, wenn die laufen, dann laufen, sage ich mal, die Hauptanforderungen an unser System durch, nicht bis ins letzte Detail.
Da hätte ich noch eine ketzerische Frage zu. Jetzt hast du ja gesagt, ihr habt Unit Tests und andere Tests auch irgendwie alle noch und da scheinbar auch eine relativ gute Abdeckung. Bei einem End-zu-Ende Tests hast du ja eigentlich immer das Problem, der sagt dir zwar das was kaputt ist, aber er sagt dir relativ ungenau, was kaputt ist, weil halt nur dein Video ist nicht angekommen, fertig. Irgendwo zwischen hier und da ist es verloren gegangen. Wenn ihr aber diese ganzen anderen Tests habt und nicht so ganz ketzerisch formuliert ist, wieso braucht ihr denn dann noch End-to-End Tests? Also welchen Mehrwert bieten die denn dann noch, wenn du eh schon die ganzen anderen unteren Stufen der Test-Pyramide so abgedeckt hast?
Na ja, ein Test gibt, würde ich jetzt sagen, mir oder auch dir immer nur die Sicherheit von dem, was es testet. Das heißt, der Test Scope gibt ja an, in welchem Bereich du was verändern kannst und ein Sicherheitsnetz hast, indem du über einen Fehler informiert wirst. Und wenn du zwei Unit Tests schreibst, zwei Units, die zusammenarbeiten und du änderst irgendwie die Art und Weise, wie die zusammenarbeiten, dann hast du für diese Änderungen kein großes Sicherheitsnetz mehr.
Aber hast du da für nicht deine Contractual Tests, die genau diese Zusammenarbeit eigentlich abdecken sollten oder Integrationstests?
Ja, also es gibt ja wie gesagt Unit Tests ist ja immer die Frage, wie man die Unit beschreibt, wie groß die ist. Und gerade wenn man kleine Units hat, dann wird man sehr genau informiert, wenn in einer kleinen Unit etwas kaputt geht. Allerdings gerade wenn man mehrere Units, die zusammenarbeiten, sage ich mal, immer nur einzeln testet, dann testet man ja nie das Zusammengreifen dieser. Und wenn ich dann an der Art und Weise, wie die zusammengreifen, etwas ändere, habe ich häufig kein Sicherheitsnetz, was mir sagt okay, das funktioniert in dem Zusammenspiel so wie vorher auch. Also ein konkretes Beispiel kann ich auch nennen. Zum Beispiel, wenn ich mir überlege, okay, wie hole ich irgendwie einen hunderte Schritten Sachen aus der Datenbank. Dann habe ich vielleicht einen Service, der gibt die hunderte Schritte vor und die Datenbank sorgt dafür, dass die hundert Schritte irgendwie rauskommen. Dann müssen die aber ja die gleiche Sortierung verwenden. Und wenn ich jetzt beide Unit teste und sage okay, der eine macht das so und der andere macht das so, aber diese implizite Abhängigkeit, dass der eine natürlich eine Ordnung vorgeben muss, die von dem anderen erfüllt werden kann, damit ich am Ende alle habe, das ist vielleicht in keinem Unit Test abgedeckt.
Das heißt, da habe ich was. Wenn ich das kaputt mache, sind meine Unit Tests immer noch grün, weil jeder Unit sagt okay, ich verhalte mich so wie ich sollte. Der eine macht hunderte Schritte, der andere gibt hunderte Schritte raus. Dass es aber am Ende ein Ganzes ergibt, das sagt eben kein Unit Test.
Also warum ich dich da so gegrillt habe, ist ja eigentlich. Ich glaube, es ist alles richtig, was du gesagt hast. Aber ich glaube, das ist eine Diskussion, die ganz viele Entwickler da draußen ganz oft führen müssen. Das ist glaube ich, wichtig, einmal aufzuzeigen, was wirklich der Mehrwert ist, weil nicht jede Firma ist so testaffin und testgetrieben wie ihr. Und ich glaube, es gibt viele Entwickler da draußen, die würden gerne testgetrieben arbeiten, die würden gerne mit mehr End-to-End Tests auch arbeiten, aber die kämpfen da manchmal vielleicht gegen, ich sage mal, bürokratische Windmühlen, wo sie halt eben sehr genau darlegen müssen, warum wollen sie denn das jetzt machen? Und warum ist denn dieser hohe Invest, den wir eben auch angesprochen haben, das alles mal zum Laufen zu bringen, warum ist es das denn wert? Ich glaube, da hast du das schon gut abgerissen.
Ja, aber ich glaube, der Wert ist ja auch tatsächlich.
Also.
Man muss ja mal fragen, okay, wenn du jetzt eine neue Version deployst, bist du dir sicher, dass noch alles so funktioniert wie vorher? Kannst du da sagen Ja, ja, wahrscheinlich oder weißt du es nicht? Und gerade wenn man irgendwie auch mal kurzfristig vielleicht eine Version hochziehen muss, weil irgendein Sicherheitsaspekt mit reinspielt, dann ist man zum einen wirklich sehr, sehr handlungsfähig, weil man weiß okay, ich ändere jetzt was und ich weiß zu 99 Prozent meine Haupt-Business-Cases, die funktionieren so wie vorher. Und zum anderen hat man eben wirklich auch gerade was Wartung angeht einen riesigen Vorteil. Weil ja, gerade wenn man Systeme hat, wo man sagt okay, da gehen wir jetzt in den Wartungsbereich über, der wird nicht mehr aktiv weiterentwickelt, da entstehen ja trotzdem immer mal wieder kleinere Aufgaben, wo man vielleicht kein Know how mehr hat, wer da das letzte Mal vor einem halben Jahr oder vor einem Jahr was gemacht hat. Man muss Versionen vielleicht auch innerhalb von einem Tag mal updaten können und hat keine Zeit, dass irgendwie fünf Leute sich da noch eine Woche hinsetzen und das manuell durch testen. Und ich glaube, je mehr man die Frage nach den Kosten stellt, desto mehr muss man halt auch wirklich fragen Was.
Habe ich denn.
Für einen Wert und was habe ich für eine Aussage für mein System als Entwickler, wenn ich es nicht Ende zu Ende teste, wenn ich nicht nach jedem Deployment mit einem guten Gefühl sagen kann Okay, die Haupt-Cases funktionieren noch. Weil ich glaube, der Schaden, der entsteht, wenn es mal nicht so ist, der ist eben auch sehr, sehr groß.
Ja, ich glaube, da sind wir alle bei dir.
Ja, nur der Schaden. Genau. Es kommt immer noch wahrscheinlich auch auf die Kritikalität des Systems an und ich sage mal so, wir entwickeln ja Games und zumindest bei den Web Games ist es so, dass wir durchaus auch mal mit dem Risiko von, also wir sind Ende to Ende Tests nicht sehr gut aufgestellt, es mal, obwohl der Jojo ist heute, Jojo war heute leider krank. Jojo hat gesagt, sie machen viel Ende to Ende Tests, deswegen bin ich mal gespannt, wie es eigentlich bei Frau Pickes mittlerweile aussieht. Also ich spreche für unsere Weblandschaft und es ist zumindest so, was man zumindest damit einpreist bei uns ist der Fakt mit, wenn es bei ein paar Prozent für eine kurze Zeit mal kaputt ist, was wir sehr schnell mitbekommen bei der Menge an Usern und sowas, ist es durchaus verkraftbar. Deswegen kann man aber glaube ich nicht in den meisten Fällen unbedingt sagen. Bei uns fällt es halt auch sofort auf, wenn irgendwas nicht funktioniert. Das haben wir vielleicht einen kleinen Vorteil im Vergleich.
Jetzt bin ich ja auch kein Spieleentwickler. Ich bin ja nur hier für die Podcasts und die Videos. Aber ich kann mir schon vorstellen, dass Spiele auch generell schwieriger endto end zu testen sind, weil sie a) wahrscheinlich einen komplexeren State haben als die Durchschnitts B2B Anwendungen zu jedem beliebigen Zeitpunkt und wahrscheinlich auch ein sehr viel Customizederes UI, was schwieriger ist mit einem Web-Driver zum Beispiel anzusprechen, Input zu simulieren, Touch-Targets und all sowas.
Und bei uns noch mit dazu kommt, dass wir auf Plattformen arbeiten, wo viele der abhängig, also zum Beispiel wir entwickeln ja auch Spiele für Facebook und Facebook Incent Games und da haben wir schon oftmals und das halt ganz viele Dinge super von den Spezifika dieser Plattform abhängen. Wenn wir davon alles irgendwie wegfaken, dann ist halt, also viele davon hängt einfach davon ab, dass es in der Plattform läuft und asynchrone Mechanismen und so weiter. Aber deswegen hatte ich ja vorhin so ein bisschen gefragt, weil ich mich noch interessieren würde, vielleicht kannst du darüber noch mal sprechen bei eurem einen Frontend, was ihr macht, so wie ist eure Testabdeckung, was ihr Ende-zu-Ende Tests sind im Vergleich von wo ihr Frontend mit Backend testet zu Microservices, weil es schon so ist, also die zumindest in der inmeiner in meiner Wahrnehmung als wir das. Wir hatten es bei, ist jetzt schon als wir bei Lothar angefangen vor fünf Jahren, da haben wir mal ein Game probiert, wirklich so End-zu-Ende-Test mit auch wir haben Cucumber damals genutzt, so was zu machen, wo wir gemerkt haben, sobald die UI mit reinkam und so was, Facebook war dann bei uns ein großer Teil, aber es gibt dir einfach noch mal eine ganz andere Komplexität da mit rein, so als wenn man nur in Anführungsstrichen – auch das ist schon eine hohe Aufwand, ich will das gar nicht diskreditieren – seine Backend Microservice Monolithen Landschaft irgendwie testet.
Also wie ist da eure Erfahrung? Hast du das Gefühl, es ähnlich einfach und einfach nur man muss andere Challenges lösen, oder?
Wie sind eure Erfahrungen? Also tatsächlich ist unsere Testabdeckung in den Backend Bereichen deutlich höher, auch auf Ende-zu-Ende-Test-Ebene als jetzt in unserem Frontend, was wir Ende-zu-Ende testen. Die Challenges sind schon ein bisschen höher aus meiner Sicht, weil wir gerade mit Cucumber so ein bisschen gefühlt den Zustand verlieren zwischen den Schritten. Also Cucumber ermöglicht es eben, das Ganze eher so in Prosa zu formulieren. Wenn ich jetzt auf der Startseite bin und ich klicke auf das Menü und ich navigiere dann dahin. Da haben wir auch Tests, die wirklich so, sage ich mal, Basic unsere Navigation auf unserer Website testen, aber in einem deutlich geringeren Umfang. Und es ist aus meiner Sicht.
Auch zu.
Einem gewissen Grad ein bisschen komplexer. Aber gerade auch mit einem guten Page Model Object lassen sich da eigentlich auch sehr gute Ende-zu-Ende Tests schreiben. Also dass ich wirklich okay, Page Model Object ist sowas, ich habe die verschiedenen Seiten auf meiner Website, denen ich Objekte in meinen Tests zuordne, sodass ich quasi auf einer Startseite starte und die Startseite hat ein Menü und dann kann ich wirklich so eine Fluent Language. Also kann ich wirklich sagen okay, ich bin auf der Startseite, ich öffne das Menü, ich navigiere zu der Seite. Ich erwarte, dass jetzt die neue Seite da ist und bekomme als Rückgabewert dann quasi den Inhalt der neuen Seite, wie ich da interagieren kann. Damit schafft man es eigentlich ein gutes Abstraktionslevel auch in UI Tests oder Frontend Tests zu bringen.
Das wollte ich gerade sagen, dass ist eure Abstraktionsebene zwischen dem Web-Driver oder dem Library, was ihr dafür verwendet und dann eben der objektorientierten oder funktionalen Programmierung, was immer man da so macht, dass man halt eben auch mit dem State der Anwendung reden kann in seinem Quelltext sozusagen.
Genau, also dass ich eine Methode habe, die heißt halt Login und die ist dann, die kapselt das Spezielle ab. Ich muss nicht sagen, klick da hin, gib das ein, mach das, sondern ich habe vielleicht eine Funktion, die heißt Login und die hat dann quasi ein Abstraktionslevel, was man verstehen kann. Okay, das logt den Nutzer ein. Und was dann da hinten drin steht, das ist quasi ein Implementierungsdetail. Und nach Login bin ich einfach auf meiner Seite im eingelockten Zustand.
Das ist so ein Bereich von End-to-End Tests, der mich schon immer so fasziniert hat. Weil am Ende hängst du ja gerade bei den Frontend Tests noch mehr schon sehr an dem UI oder wenn du mit einem Backend End to End Tests an deiner REST API. Aber du hast ja immer diesen diesen Contract dazwischen. Und gerade UI ist ja was, was sich schon ab und zu auch mal ändern kann. Was sind da so eure Erfahrungen? Wie schafft ihr es quasi robuste Tests zu bauen, sodass du, wenn ich sage mal ganz salopp, du benennst deinen Login Button und auf einmal gehen dir alle Tests kaputt, weil kein Test mehr diesen Login Button findet, weil er auf einmal anders heißt, an einer anderen Position ist, irgendwie anders gemarkert ist. Wie schafft ihr es, möglichst resiliente Tests zu bauen?
Im Grunde tatsächlich machen wir relativ wenig. Viel geht inzwischen glaube ich sehr gut über Aria Label, was eh was ist, was auf viele in den nächsten Jahren verpflichtend zukommt, dass die Seiten, ich glaube es ist gesetzlich beschlossen worden, immer mehr Barrierefreiheit zulassen müssen und da eben dann auch eine Möglichkeit bieten für uns als Entwickler sage ich mal eine gute Schnittstelle zu haben, weil natürlich so eine Website dann zu einem gewissen Grad natürlich auch nicht nur für Leute, die sie nicht richtig, vielleicht in aller Form wahrnehmen können, wie wir das tun, sondern dann eben auch aus der Computersicht besser angesprochen werden können.
Am Ende ist dein Web-Treiber auch nur ein Screenreader.
Genau.
Aber was würdest du aber sagen, dann eure bzw. Ihr macht in dem Frontend-Teil nicht so viel, Ende-zu-Ende Testabdeckung, ist es, was würdest du runterbrechen ist dann jetzt am Ende der Grund dafür, weil es mehr Komplexität mit sich bringt, weil es bisschen weniger kritische Anwendung ist? Oder was ist bei euch der?
Weil es eine weniger kritische Anwendung ist, weil bei einem neuen Deployment auch das manuelle Testen deutlich einfacher ist, dass wir sagen können Okay, wenn wir jetzt auf einer Beta deployen, dann testen wir zu einem gewissen Grad noch mal manuell, was vielleicht in Summe einfach weniger kostet, unser Frontend weniger häufig einen Versionsupgrade bekommt, sage ich mal. Das sind eigentlich für mich so die Hauptargumente.
Aber wenn dann so ein bisschen andersherum gefragt, wie viel Ende zu Ende Testing ist notwendig, damit es mir was bringt? Also du hast ja gesagt, duman will eine gewisse Sicherheit haben. Ich habe das Gefühl, ihr habt bei den Services dadurch, dass ja auch Test getrieben vorgeht und gefühlt irgendwie das zuerst mal den Akzeptanz dort definiert, glaube ich, dass ihr mit den UI Unit Tests und den ganzen anderen Dingen aus der Testpyramide da eine sehr hohe Sicherheit habt, wenn ihr deployt. Wenn ihr jetzt aber sagt bei den Frontends, na gut, wir können ja auch im Nachgang noch manuell testen und so. Wie viel bringen mir dann die Ende-zu-Ende Tests im Frontend, wenn sie gar nicht ganzheitlich alles testet? Oder testet ihr damit eher Edge Cases oder wie geht ihr da vor?
Also du hast ja selbst schon gesagt, ihr bekommt es zum Beispiel sofort mit, wenn bei euch was schief geht, wenn ihr was Neues deployt und irgendwas klappt nicht, dann bekommt ihr direkt ein Feedback, weil die Nutzer das innerhalb von kurzer Zeit rückmelden. Und ich finde, das sind immer Entscheidungen, die muss man tatsächlich in so eine Teststrategie mit einfließen lassen. Also es ist nicht so, ich schreibe Ende-zu-Ende Tests und bin dann irgendwie fertig oder jetzt mache ich das und dann habe ich die Sicherheit, sondern man muss sich überlegen, wie sieht meine Teststrategie aus. Da sind für uns im Backend Ende-zu-Ende Tests ein großer Teil, weil wir nicht in allen unseren Systemen quasi betafähig sind, weil wir relativ viel testen müssten, was relativ manuell testen müssten, was irgendwie schwer zu testen ist, also gefühlt einen Zustand zu erzeugen und dann irgendwie über APIs abzufragen, das ist was anderes, als sich durch eine Website zu klicken, wenn man mal neu deployt. Und natürlich ist es auch die Frage, wie teuer ist ein Fehler, wo man entscheiden muss, okay, wie schnell fällt er auf, wie teuer ist er, der einem dann sagen muss, okay, in dem und dem Umfang macht es in meinem speziellen Use Case Sinn, Ende zu Ende zu testen.
Ich würde die Frage einmal umdrehen und jetzt haben wir ja so, wo ist es sinnvoll, dann End-zu-End zu testen? Würdest du auch sagen, es gibt einen Bereich, wo es überhaupt nicht sinnvoll ist, auf End-zu-End Tests zu setzen?
Also wie schon gesagt, wir haben ja auch ein, zwei Sachen, die wir jetzt eher intern nutzen, also Monitoring Frontend, wo ein paar Graphen angezeigt werden, wie unser System sich verhält. Das würden wir nicht Ende zu Ende testen, weil wir wir sehen, also wir schauen jeden Tag drauf, wenn wir neu deployen würden, dann schauen wir eh auch drauf und wir kriegen Fehler direkt mit. Wir sind die Leute, die es selbst sehen, die im Zweifel irgendwie innerhalb von einer Minute wieder zurückrollen könnten. Was vom Umfang her so klein ist, dass es tatsächlich auch noch irgendwie in kurzer Zeit manuell zu testen ist. Und das ist für mich ein Use Case, wo ich sage okay, da ist der Trade-off einfach negativ, das Ende zu Ende zu testen automatisiert.
Und vielleicht jetzt noch mal den Unterschied von, den du vorhin aufgemacht hast, von Ende zu Ende zur Akzeptanztest, wo ihr sagt, ihr nutzt es als synonym und dadurch auch dadurcheure lebende Dokumentation ist und ihr den Akzeptanztest auch selbst definiert bei euch im technischen Team so. Wenn es jetzt... Also ich frage mich so ein bisschen, ist denn diese, wir haben es vorhin schon mal kurz angesprochen, aber dieser Punkt mit, dass wir CubeCumber nutzen und wirklich diese Abstraktion Schicht auf die Akzeptanz Ebene heben, dass man das in Prosa hinschreiben kann. So wie, wo würdest du da sagen, das ist jetzt sinnvoll oder nicht? Wo könnte ich sagen, okay, Ende zu Ende Tests machen, ich brauche diese Prosa Schichten. Ich habe jetzt das Beispiel jetzt hier bei uns bei den Games, wenn wir jetzt sagen würden, wir testen unsere Services für die Games Ende zu Ende, wo wir oftmals weniger Abhängigkeit haben. Wir haben vielleicht ein paar Notification Services oder so was, wo wir irgendwie vielleicht mal einen Stap irgendwie dafür implementieren müssen. Aber ansonsten ist es auch so, dass da jetzt kein fachlicher Ansprechpartner kommt, der da jetzt unbedingt nachfragen wird. So inwiefern muss ich da drüber nachdenken?
Mach es jetzt mal einen Ende zu Ende Test. Wenn ich jetzt irgendwie unseren Service dort testen will, gehe ich jetzt auf Cucumber und mache es in Prosa oder nehme ich einfach ein Testing Framework und teste einfach nur, keine Ahnung, mit Gest und superrequest teste ich einfach nur meinen Rest Endpunkt und sage einfach ich teste die komplette Strecke bis hinten durch, aber schreib einfach mein Test in JavaScript so.
Also ich sehe wirklich einen großen Mehrwert davon, auch als Entwickler einfach mal diese Entwicklungsbrille bei den Tests ein bisschen abzusetzen und sich wirklich einfach nur auf die Anforderungen zu spezialisieren. Also wirklich zu sagen okay, ich möchte, dass die Anforderung eigentlich im Vordergrund steht. Ich möchte nicht so sehr direkt in eine technische Sprache, sondern ich möchte wirklich erst mal meine Anforderungen sauber runterschreiben können. Das, finde ich, schafft einen sehr großen Mehrwert. Und da hilft mir doch tatsächlich die Prosa, auch wenn ich Anforderungen eins zu eins technisch runterschreiben könnte, dass ich probiere, mein System wirklich mit so einer User Sicht zu sehen. Also für mich auch ganz wichtig am Ende, egal ob das Microservice ist und egal ob ich ein Monolith oder ein Groß und klein oder wie die Infrastruktur ist, am Ende ist es ein Softwareprogramm und ein Softwareprogramm macht aus dem Input irgendwie einen Output und erfüllt die Regeln, die wir Anforderungen nennen. Also die Anforderungen sind eigentlich das Essenzielle. Die Anforderungen ändern sich nicht. Und ich finde es ganz wichtig, auch gerade als Entwickler wirklich zu sagen okay, der erste Schritt ist, die Anforderungen einmal sauber runter zu schreiben, einmal richtig zu verstehen, einmal wirklich aus Sicht des Anwenders zu verstehen, was möchte ich, bevor ich in eine technische Implementierung gehe?
Und da finde ich es tatsächlich hilfreich, einfach das in Prosa schreiben zu können.
Es gibt ja auch immer noch so dieses Wunsch-Szenario, dass wenn du die Möglichkeit hast, deine Tests in Prosa zu artikulieren, dass du auch Leute enabelst, Tests zu schreiben, Anforderungen zu schreiben, die sonst nicht mit der Entwicklung zusammenhören, dein Product Owner, deinen Projektmanagement, wie auch immer. So habt ihr, habtihr damit Erfahrung, zu jemandem nicht-Technischen zu gehen und sagen „Guck mal hier, wir haben hier dieses Framework. Damit kannst du in deiner Sprache, in unserer geteilten Domänsprache Anforderungen formulieren, Tests formulieren et cetera et cetera und damit uns quasi helfen sicherzustellen, dass das, was du von der Software willst, dass das am Ende des Tages auch sauber genau nach deinen Anforderungen umgesetzt ist. Ich habe das ehrlicherweise noch nie geschafft, weil wir immer an diversen Kleinigkeiten daran gescheitert sind. Aber habt ihr so was.
Schon mal versucht?
Jetzt haben wir diese Aufteilung nicht quasi, dass wir jemanden haben, der da die Anforderung vor uns schreiben würde. Aber ich glaube, was es hilft, ist, dass wenn, wenn irgendwann mal so das Vertrauen, also es schafft eine Menge Vertrauen zwischen Entwickler und Anforderungsseite. Wennman so Tests zeigt und schreibt und die zumindest nachvollziehbar sind. Also ich habe es ganz oft in einem Review gesehen, dass man gesagt hat okay, wir zeigen die Akzeptanz Tests, die jetzt grün sind. Und wenn das Vertrauen da ist, dass ein Product Owner oder eine Product Ownerin weiß okay, wenn das da so steht, dann hat mein Entwicklerteam das so umgesetzt, dass es funktioniert, dann kann das für mich ein riesengroßer Schritt sein, wirklich dieses Vertrauen okay, Anforderungsseite zu Entwicklungsteam massiv zu stärken, weil ein Review, was man vielleicht aus dem Scrum Prozess jetzt kennt, einmal alle zwei Wochen, vielleicht eine halbe Stunde oder so, da ist es ja gar nicht möglich für einen Product Owner, sage ich mal, auch zu sagen okay, ich nehme das ab, ich sage, das ist jetzt alles richtig oder so. Und ich glaube, an so einer Stelle können wirklich auch Akzeptanztest ein riesengroßer Enabler sein, einfach dieses Vertrauen zu schaffen und auch zu zeigen, hey, wenn ich in den Akzeptanz was ändere, dann wird der rot, weil dann verhält sich nicht so, wie wir es erwarten.
Und ich glaube, das ist schon ein richtig gutes Mittel. Aber tatsächlich in einem Projekt, wo die Anforderung zweiter Akzeptanz ist, geschrieben hat, da war ich bisher auch noch nicht. Auch wenn es natürlich irgendwie der Wunsch ist, dass das vielleicht so passiert.
Was mich noch interessieren würde, wir haben ja uns auch darüber unterhalten, dass ihr viele Clients und Ähnliches habt und auch du hast Beispiele für genannt, wie ihr irgendwie Stopps, Fakes, Mocks, wie auch immer nutzt. An welchen Stellen entscheidet ihr denn, ob ihr oder gibt es da eine klare Antwort darauf, ob ihr externe Abhängigkeiten mockt, Fake oder das echte benutzt. Also beispielsweise Datenbank Queue Systeme so, also ist da nutzt ihr da Fakes oder nutzt ihr die wirkliche Datenbank bei euren End to end Tests? Wenn ihr in eine Docker Umgebung hochfährt, ich weiß nicht, was ihr als Mongo hast du glaube ich gesagt, nutzt ihr dann ein Mongo Image oder wo macht ihr da die Grenze? Wann entscheidet ihr euch dafür was zu faken? Solange ihr es als Image benutzen könnt, nutzt ihr das Richtige?
Genau. Also solange wir da ein gutes Image finden, also wie gesagt, bei mongoDB und Rappit MQ ist es bei uns so, die werden einfach in der Produktionsversion in unsere Docker Umgebung hochgefahren für die Ende zu Ende Tests und alles was quasi extern ist, also was wir nicht selbst entwickeln, mocken wir in der Regel weg.
Und gibt es da irgendwie bei so Dinge, die z. B. In diesen, wenn ihr die echten Produkte nutzt, ich habe z. B. Ein Beispiel. Vielleicht nehme ich da mit den Pick of the Day vorweg von mir, aber ich habe jetzt gerade für mein Schwager eine Anwendung gebaut mit Timestale DB, also auf Postgreif basierend und die bieten ein bisschen Feature, mit Zeitreihen Daten arbeiten zu können. Sie bieten dann beispielsweise auch Features an, dass man auf einer roten Tabelle, wo man irgendwie, keine Ahnung, minütliche, sekündliche Daten bekommt, davon in gewissen Intervallen sich Time Buckets erstellen kann, dass man sagt, okay, aggregiere mir diese Daten auf täglicher, monatlicher, wie auch immer Basis. Und das ist etwas, was nicht real time passiert, sondern irgendwie mit Policies, die man definiert in gewissen Intervallen. Und wenn es aber jetzt sagen wir ein anderes Feature geben würde, was ich schreibe minütliche Daten da rein, es gibt ein anderes Feature, was tägliche Daten rausholen will, wo ich mich in so einem Fall frage, okay, jetzt bin ich dabei, dass ich sozusagen an einer, meine Applikation hängt an einem Feature von einer Abhängigkeit. Und die möchte ich jetzt vielleicht irgendwie Ende zu Ende testen, dass ich sage, ich gebe Daten rein, will sicherstellen, dass das Ganze dann auch passiert.
Ist es was, was ich dann nicht Ende-zu-Ende testen würde, sondern eher einen Integrationstester schreiben würde? Oder wie geht ihr bei so Fällen vor? Oder habt ihr so Use-Cases gehabt, wo ihr so auf die Spezifika der Datenbank oder sowas einfach, die ihr benutzen müsst?
Das haben wir wenig. Aber es kann tatsächlich auch. Also unser Anspruch ist immer, wir müssen unsere Ende-zu-Ende Tests laufen, auch wenn ich in der Bahn sitze. Das heißt alles, was mit Internetverbindungen ist, ist eherschwierig. Also wenn das externe System sage ich mal nur übers Internet verfügbar ist, dann ist es bei uns aktuell so, dass wir es in der Regel nicht in Produktion verwenden, sondern dass wir dann eben einen entsprechenden Fake oder Stab oder Test-Dubbel verwenden. Aber ich habe auch damit schon gute Erfahrungen gemacht, wenn man wirklich irgendwie gegen ein sehr stabiles System entwickelt, sage ich mal, vielleicht auch auf einer auf einer eigenen Umgebung oder so, dass man sagt okay, wir nutzen für unsere Tests dann tatsächlich das produktive System.
Aber das wäre das Beispiel, man kann es genauso gut auch lokal hochfahren, was dann auf dieser, ist einfach nur etwas, was beispielsweise in diesem Produkt zeitlich verzögert passiert, so. Und wo ich mich dann, vielleicht müsste ich irgendwie eine Implementierung bauen, die Zeit nach vorne zu drehen bei der Datenbank oder ähnliches oder das manuell anzustoßen, dass ich einfach so vielleicht in meinem Cube Camper die Wenn-Bedingung habe, wenn die Daten verarbeitet sind, dann kann ich sie retrieven oder sowas. Und ich definiere die Wenn-Bedingung, die dann irgendwie die Datenbank, vielleicht gibt es ja auch irgendwelche Trigger, das voran zu drehen.
Das ist halt so die Frage nach dem Scope. Weil was du ja gerade beschreibst, du willst ja eigentlich deine Dependency testen. Wenn du nämlich 24 Stunden warten musst, bis deine Policy greift, dann testest du ja nicht deine Anwendung, sondern du testest eigentlich die Policy von der Datenbank, sodass man eigentlich den Case machen müsste: Für deinen Test nimmst du halt nicht die Policy, die analog zu dem Produktion System ist, sondern setzt halt die Policy runter auf minütlich 30 Sekunden, wie auch immer, weil das ja nicht dein Scope ist. Dein End-to-End Test dient ja nicht dazu, deine Dependency zu validieren, sondern nur deine eigene Businesslogik eigentlich zu testen. Und ich glaube da, also gerne unterbreche mich da ruhig, aber ich glaube, da ist es valide, abweichende Parameter quasi zu nehmen für sowas.
Genau das machen wir auch ganz oft, dass wir selbst bei unseren eigenen Applikationen, sag ich mal, hier und da zum einen die Zeit variieren können. Also das ist so ein Punkt, der bei uns wichtig ist, dass ein Video z. B. Samstags 20 Uhr veröffentlicht wird. Da haben wir unsere Applikation so erweitert, dass wir quasi so ein bisschen Zeitmanipulation nach vorne. Also wir können Vorspulen in Anführungsstrichen in unseren Systemen implementiert haben für den Akzeptanztest. Aber genau das ist schon was, gerade was so Konfiguratives, wo man dann sagen muss okay, Abwägung zwischen Produktionsnähe und Testbarkeit. Und wenn es testbar ist, wenn ich es auf zehn Sekunden setze oder auf zwei Sekunden und trotzdem noch relativ produktionsnah, dann ist das was, was wir auch so machen würden, dass wir sagen würden okay, wir konfigurieren es jetzt einfach so, dass es für unseren Test funktioniert und sind dann ein bisschen weiter weg von Produktion.
Abgesehen.
Von so Zeitreise Featuren, gibt es irgendwas in eurem End-to-End-Testing Setup, wo du sagst, das fehlt noch, das hätte ich gerne, das würde ich mir mit einem Zauberstab gerne herbeiwünschen? Was ist so the next big thing für euch da?
Also tatsächlich, wir haben ja auch ein bisschen was dazugelernt. Wir haben anfangs häufig noch so Extension Sizen, die bei uns gebaut. Das heißt, wir bauen die Applikation doppelt einmal für die Produktivumgebung, einmal für die Ende-zu-Ende-Testumgebung, wobei dann die Applikation für die Ende-zu-Ende-Testumgebung eben dieses Zeitreise-Feature hast du es gerade genannt, mit drin hat und die in Produktion natürlich nicht, weil wir den Code da nicht mit drin haben wollen. Und gerade der Punkt wirklich mit Asynchronität über Microservices oder Eventual Konsistency, dass der eine schon was weiß, was der andere noch nicht weiß, das ist wirklich eine Haupt-Herausforderung für uns gewesen, dass wir da einen sauberen Stand haben, dass nicht der Test dann rot wird, weil der eine Service noch nicht so weit ist. Oder bei dem einen läuft der eine Service schneller als beim anderen. Dann hat man häufig Tests, die sind bei manchen Entwicklern grün, bei den anderen rot. Da wäre es einfach wirklich schön, wenn es irgendein Framework gibt, was man implementiert, sage ich mal, was einem das abnimmt, wo man sagt okay, ich möchte warten, dass das fertig ist und dann einfach deutlich robustere Tests hat.
Eine Nachfrage dazu. Warum ist es für euch wichtig, dass beispielsweise der Zeitreihen, das Zeitreihen Feature nicht mit, also es geht ja nur darum, ob es mit rein gebundelt ist in das Produktion Image. Ich hätte jetzt erwartet, so wie wir es häufig implementieren, ist einfach zu sagen, es wird über ein Environment Variablen gesteuert, in welchem Environment, also einfach nur in welchem Environment befinde ich mich und könnte es dann im Endeffekt einfach ausschalten, bisschen so Feature-Flack-mäßig. Warum ist es für euch sehr wichtig zu sagen, es muss ein anderes Image sein, wo ich meine Tests gegen laufen lasse?
Ich würde sagen sehr wichtig. Bei vielen Sachen haben wir am Anfang quasi abgewogen: Ist es etwas, was wir eher konfigurativ desabeln wollen? Wie du gesagt hast, man setzt eine Property, ob das geht oder nicht? Oder bauen wir wirklich eine eigene Applikation? Gefühlt haben wir uns mehr in die Richtung wir schalten es konfigurativ ein und aus entwickelt. Aber anfangs war für mich schon die Frage okay, möchte ich jetzt wirklich diesen Code in Anführungsstrichen auch die Dependencys mit in meine Produktivumgebung haben oder nicht? Es gibt ja auch Dependencys, die kommen aus dem Spring Boot Umfeld, wo je nachdem ob jetzt ein Spring Boot Starter Package mit drin ist oder nicht, gewisse Sachen dazukommen oder nicht? Gerade diese Synchronität, dass die Services Bescheid sagen, wann sie fertig sind und wann nicht, das haben wir über Aspekte gelöst in Spring Boot. Das ist halt schon ein größeres Package, was wir sonst nicht brauchen. Und was vielleicht... Was vielleicht hier und da auch tatsächlich eine zusätzliche Funktion oder Risiken mit sich bringt, wo wir dann einfach sagen, wir fühlen uns besser, wenn es halt nicht im Produktivcode ist.
Ja, auf jeden Fall auch. Ich habe mich nur gerade vor dem Hintergrund so ein bisschen gefragt, ob es Sinn macht, dass es dann wirklich das Produktiv Image getestet wurde, sodass es da auf jeden Fall nicht noch... Könnte ja auch sein, dass es dann beim... Rein theoretisch, wenn beim Bundling eben noch was anderes mit rausgenommen wird, dass da irgendwas im Code mit drin ist, der... Aber gut, das ist einfach für euch wichtig sicherzustellen, dass das Produktiv Image sich genau gleich verhält, wie das Test Image und eben nur diese Aspekte.
Da raus gebundelt werden. Genau, aber das ist auch wieder von Use Case zu Use Case unterschiedlich. Ich habe auch aus der App Entwicklung gesehen, dass es Leute gibt, die wirklich darauf Wert legen, dass das exakt gleich gebundelt ist und irgendwie die Signatur dann zwischen den verschiedenen Deployments noch geändert wird, aber das gleiche, das gleiche Bundle am Ende wirklich deployt wird. Da muss man dann wirklich entscheiden, was für einen wichtig ist, sage ich mal, ob man sagt okay, ich habe eine gute Testbarkeit und das Risiko ist eher gering, dass da ein Unterschied zwischen Ende zu Ende Test und Produktion ist oder ob man halt wirklich sagt okay, mir ist wichtig, dass die gleichen Dateien eins zu eins sind und ich nutze die.
Ich hätte da eher interessiert, ob es einen expliziten Grund gibt, warum ihr das nicht drin haben wollt, also irgendwie Angriffsfaktoren oder ähnliches. Ob irgendwas, wo ihr sagt, das ist für uns wirklich kritisch, wenn es damit drin wäre. Ich glaube, auf jeden Fall ist es immer eine falsche Falle Entscheidung. Eher so der Negativfall, also irgendwas, was auf jeden Fall, wo ihr sagt, deswegen darf es dort nicht drin sein, so aus eurer Sicht?
Gibt es so hart nicht bei uns. Aber ich hätte schon gesagt, ich glaube, ich glaube, dass wir für Aspekt auch einen Spring Boot Starter nutzen, der dann Dinge mitbringt, die jetzt nicht so eins zu eins offensichtlich sind und wo ich dann sagen würde, okay, das ist für uns ein Grund, das so zu machen, aber es ist kein harter Cut.
Auch in dem Umfeld ist es nicht so kritisch. Ich glaube, wenn du jetzt vielleicht medizinisches Equipment oder sowas herstellst, da ist es wahrscheinlich super kritisch, dass die Software, die du getestet hast, also Signatur genau die ist, die am Ende irgendwie auch in Produktion ausgerollt wird oder so.
Ja, ja, definitiv. Okay, vielleicht ein Aspekt, den mich noch interessieren würde, kannst du noch kurz zwei Sätze darüber verlieren? So habt ihr Ende-zu-Ende-Tests von vornherein beim Start eurer Entwicklung als sozusagen Leitfaden definiert und habt Ende-zu-Ende-Tests von Anfang an gemacht. Und in beiden Fällen würde mich interessieren, wie einfach würdest du es betrachten, das auch in einer Bestandslandschaft irgendwie mit reinzubekommen? Also ist das für euch zu leicht, wenn man das von vornherein gemacht hat? Aber ihr seid ja auch erst später damit gestartet.
Also wir sind ein bisschen später damit gestartet und die Kosten werden natürlich höher, weil das erste, was man braucht, ist Testbaren Code. Wenn man von Anfang an keinen Testbaren Code schreibt, ist es schwierig, irgendwann Tests dafür zu schreiben. Nichtsdestotrotz sage ich mal, gerade wenn man ein Projekt auf der grünen Wiese anfängt, dann wird das erste wahrscheinlich nicht Ende zu Ende Test sein. Da ist wirklich irgendwie auch gerade das Ziel in den ersten Iterationen, sag ich mal, was hinzustellen, damit man Feedback bekommt. Da können Tests natürlich helfen. Aber für mich ist es auch. Also zum einen ist es wichtig, früh damit anzufangen, damit die Kosten klein bleiben. Zum anderen ist es natürlich was, was für den Endnutzer nicht direkt Wert schafft, sondern erst sich über die Zeit auszahlt. Das heißt, das ist für mich etwas, wo man einfach dann ab einem gewissen Punkt stetig rein investieren sollte. Also ich würde es nicht in den ersten drei Sprints machen, sage ich mal, aber ich würde schon probieren, dann möglichst zeitnah einmal so eine Ende zu Ende Anforderung zu formulieren.
Okay, vielen Dank. Würdest du sonst sagen, wir haben noch aus deiner Sicht irgendwas zu Ende, zu Ende Tests vergessen, was du noch unbedingt sagen willst, irgendwas, was wir hätten fragen sollen? Oder denkst du, warum sind sie darauf nicht eingegangen? Das war das Wichtigste, das Beste, das Schlechteste?
Ich finde, es gab ja so die Frage warum, es geht ja auf dieses sprachliche Level. Warum nutzt du so was wie Cucumber, das irgendwie in einer Prosa Form zu formulieren? Und da finde ich tatsächlich es eigentlich gerade ganz spannend, was so in der Entwicklung passiert, weil ich habe den Eindruck, dass sich generell die Softwareentwicklung vielleicht in den nächsten Jahren mehr auf so ein Abstraktionslevel schiebt. Wir kriegen jetzt immer mehr KI, die irgendwas für einen programmiert, in welcher Qualität auch immer, aber die eigentlich dazu führt, dass man dieses Level von der technischen Implementierung immer weiter weggeht, mehr zu diesen abstrakten Anforderungen und wirklich zu sagen okay, ein System ist am Ende nur was, was einen Input in den Output transformiert, es mal so ganz pauschal zu sagen. Ich glaube, dass das schon was, was uns auch als Entwickler hilft, dass wir da einen Schritt hingehen, dass wir sagen okay, wir entwickeln alle gerne und wir sind auch alle gerne in der technischen Welt und schreiben gerne unseren Code. Aber diese Anforderung wirklich noch mehr in den Vordergrund zu rücken, ich glaube, das ist etwas, was uns in den nächsten Jahren vielleicht auch ein bisschen mehr beschäftigen wird.
Wie gut funktioniert der Co-Pilot, was Cucumber angeht?
Kann ich leider nichts zu sagen.
Weil du es nicht nutzt? Weil ich es nicht nutze. Ja, vielen Dank dafür. Raffel, auf jeden Fall vielen Dank auch fürs Quatschen über Ende-zu-Ende-Tests. Wir haben auf jeden Fall unsere allwährende Kategorie der Pick of the Days dabei Mal gucken, wer was dabei hat. Jan, für dich das erste Mal, dass du ein Pick of the Day sagen kannst. Oder ist das deine Pick of the Day End Jungferrung? Haben wir das beim Bewerbungsgespräch als so eine Pro-Podcastaufnahme machen musst, da gab es keinen Pick.
Of the Day, oder? Da gab es keinen. Ich weiß das nämlich noch. Ich hatte extra einen mitgenommen. Aber es war ja nur eine Newsfolge, die wir aufgezeichnetweiß nicht haben und dementsprechend kam es nicht dazu. Ich weiß auch nicht mehr, was das war, aber ich weiß, dass ich ein bisschen enttäuscht rausgegangen bin. Vielleicht dachte ich, ich hatte so was Cooles dabei.
Dann vielleicht, wir wollen ja eh noch mal auch die News-Folge wieder aufleben lassen, die wir damals mit dir aufgenommen haben. Und du darfst vielleicht irgendwann auch noch den Pick of the Day sagen. Aber jetzt habe ich, glaube ich, die Erwartungshaltung sehr groß gemacht, zu fragen: Jan, was ist der erste Pick of the Day in deinem Leben?
Mein erster Pick of the Day hat natürlich was mit Testen zu tun, wenn wir heute schon über End-to-End-Tests sprechen. Und zwar habe ich Panter mitgebracht. Panter ist ein Stand-A-Lown Test Library. Wassich eben super für End-to-End Tests eignet, weil es Browserautomatisierung macht über das offizielle Web-Driver Protokoll. Also jemand, der Selenium zum Beispiel schon mal benutzt hat oder so was, der wird sich da super gleich zurechtfinden und kam eigentlich so ein bisschen auch aus diesem Kontext mit, wir wollen Webseiten skrapen, aber es ist ja der Schritt von Webseiten Scraping und zu End-zu-End-Testing, der ist ja relativ klein und dementsprechend haben sie dann da später auch noch ein bisschen mehr Spezialisierung, Abstraktion und Toolchain drumherum gebaut, eben auch damit super end-to-end testen zu können.
Ja, cool. Panter. Wie der Panter.
So ist es.
Cool, packen wir in die Shownotes. Ist doch ein sehr guter Pick of the Day. Vielen Dank dafür. Raffel, ich weiß nicht, wir haben vorher gesagt, mal gucken, ob du eins hast. Hast du ein Pick of the Day für uns?
Mir ist noch keiner eingefallen. Noch keiner eingefallen. Dann lohnt sich raus, gleich noch.
Drüber nachzudenken. Dann frage ich dich gleich am Ende noch mal. Ansonsten reichen wir es nach, in die Show nutz, falls da was kommst. Dann habe ich einen Pick of the Day dabei. Ich hatte was von TimesGeld erzählt, habe jetzt aber gerade schon in der Folge gemacht. Ansonsten habe ich noch mal wieder eine Podcast Empfehlung. Hab schon mal über Spotify Product Story geredet, was ich sehr cool fand, was so die Entwicklung von Spotify entstanden, eine sehr technische Brille irgendwie aufsetzt, was ich super interessant fand, auch irgendwie acht Folgen. Und jetzt gibt es von OMR, OMR Revithold, die Sumba Story, also die Sumba Brüder, die auf jeden Fall, ich habe jetzt die ersten drei Folgen gehört, zumindestens, man kennt sie ja durchaus, Rocket Internet. Wir hatten schon ein paar CTOs von Rocket Internet Firmen hier zu Gast. Das war durchaus mal das eine oder andere Mal hier Thema und kennt man ja durchaus in der Startup Bubble. Ansonsten kennt man sie ja aus dem Yamba Spar-Abo und so ein bisschen die komplette Historie von ihnen, so wie sie zu ihrer ersten Idee kamen. Und zwar Alando wurde von Ebay gekauft, ein Alando, ein Ebay Konkurrent und der übrigens benannt wurde nach Bei-Lando von Luna.
Also sind sehr witzige Insights drin. Gut erzählt.
So viel nützliches Wissen, was man heute hier mitnehmen kann. So viel.
Nützliches Wissen. Villando, Villando. Amikus Abias oder wie es auch immer. Naja, finde ich die Sammler Story, große Empfehlung, fand ich bisher ganz cool. Empfehlungen spreche ich aus nach den ersten drei Folgen. Mal schauen, wie es weitergeht. Dann Raffael, schüttel mit dem Kopf, falls du noch was hast, schickst du uns. Wir packen es in die Shownotes. Ansonsten vielen Dank für deine Zeit. Es hat sehr viel Spaß gemacht. Jan, dir auch vielen Dank. Euch vielen Dank fürs Zuhören. Wie immer, schickt uns Feedback an podcast@programmier. Bar oder über einen unserer vielen Social-Media-Kanäle. Wir freuen uns. Schaut auch beim nächsten Mal wieder rein. Nächste Woche hören wir uns zu den AI News. Bis dann. Ciao, ciao. Ciao.
Ciao. Vielen Dank. Danke euch. Ciao.