building a product

Sven Wiegand – orgavision GmbH

005: Automatische Tests im Backend

Methoden und Herausforderungen automatischer Tests im Backend

20.04.2023 67 min

Zusammenfassung & Show Notes

Benjamin führt uns durch die Teststrategien, die wir in unserem kotlin-ktor-Backend nutzen. Dabei sprechen wir über Test-Frameworks, -Daten, -Strategien und auch deren Wirtschaftlichkeit.

Benjamin führt uns durch die Teststrategien, die wir in unserem kotlin-ktor-Backend nutzen. Dabei sprechen wir unter anderem über folgende Themen:
  • kotest (Vergleich mit JUnit (und ScalaTest), Test-Stile, Assertions, …)
  • Automatische Generierung von Testdaten
  • Property-based Testing
  • Mocking mit MockK
  • Unit- vs. Integration-Tests
  • Wirtschaftlichkeit automatischer Tests

Transkript

Heute reden wir über automatische Tests im Backend. Da sind wir wieder. War diesmal eine etwas längere Pause, weil wir letzte Woche unser Unternehmens-Offsite hatten. War auch mal wieder spannend. Drei Tage mit allen Kollegen. So richtig physisch vor Ort ist man ja gar nicht mehr gewöhnt, aber war ein Supererlebnis. Aber dadurch sind wir nicht zum Podcast produzieren gekommen.
Benjamin
00:00:42
Man muss Prioritäten setzen. Mal wieder eine so live zu sehen. Hat auch seine Vorteile.
Sven
00:00:46
Ja, definitiv. Genau. Und heute soll es um das Thema Testing im Backend gehen? Ja, da wollen wir einfach mal sehen, was wir da für Erfahrungen gemacht haben. Du hast ja auch schon in anderen Stacks gearbeitet als den, den wir jetzt gerade haben und von daher bin ich da gespannt auf deine Erkenntnisse. Weil da stecke ich tatsächlich überhaupt nicht mehr so im Detail drin und freue mich schon auf all die Sachen, die ich dann jetzt erfahren werde. Für mich ist der Podcast ja auch mal eine Hilfe, um mal wieder tiefer einzutauchen bei den Entwicklerthemen.
Benjamin
00:01:19
Du meinst dann mal wieder mitzukriegen, was wir da eigentlich so einen ganzen Tag machen?
Sven
00:01:22
Genau und die Hände über dem Kopf zusammenzuschlagen. Was für ein Unsinn. Gut. Ja. Na, steigt doch mal ein.
Benjamin
00:01:30
Ja, also erst mal vorweg wir verwenden als Testframework Kotest und nicht JUnit, was man ja auch machen könnte. Gibt es ja bei bei allem, was ja VM basiert ist, überhaupt keine Hindernisse. Das hat so ein bisschen für mich persönlich einfach auch historische Gründe. Ich bin da jetzt zum haben wir ja mit Scala gearbeitet und damit Scala Test gearbeitet. Woran ich mich dann auch sehr gewöhnt habe und was ich an vielen Stellen einfach auch sehr elegant finde, was die Art und Weise angeht, wie man Text schreiben kann. Und bei für Kotlin gibt es dann halt Kotest. Und wenn man sich mal anguckt, was der Entwickler von Kotest vorher so gemacht hat, der hat auch einiges mit Scala zu tun gehabt und ich vermute, dass er da auch als er dann bei ich glaube nämlich in die Android Entwicklung eingestiegen ist, dass er dann Scala Testfall vermisst hat, und sich deshalb daran gemacht hat, was ähnliches für Kotlin zu programmieren.
Sven
00:02:27
Das heißt, das ist gar nicht von Jet B1 Kotest. Also es ist gar nicht das, was Sie offiziell empfehlen für Kotlin, sondern das ist eines von vielen Testframeworks quasi.
Benjamin
00:02:37
Inzwischen gibt es da auch was von Checkpoints direkt selber. Wobei ich jetzt auch nicht weiß, in welchem Status das ist, also ob das überhaupt schon so der Peter Stadion verlassen hat oder so.. Keine Ahnung, habe ich mich nie mit beschäftigt, weil ganz einfach bei uns Kotest schon gesetzt war, bevor da überhaupt was kam. Und deswegen hat es sich einfach nicht nicht wirklich gelohnt. Wir hatten nie den Anlass noch mal zu sagen Na, vielleicht verwenden wir doch das.
Sven
00:03:02
Ja. Aber hat es eine gewisse Verbreitung, oder.
Benjamin
00:03:03
Wir hatten halt Kotest schon im Einsatz. Doch hat es schon. Was man schon sagen muss, dass bei Kotest ist es so, das besteht aus mehreren Teilen, die man auch unabhängig voneinander verwenden kann. Ja, das eine ist erst mal das Testframework selber, also der Punkt, wie schreibe ich Tests in Kotest? Und dann gibt es noch zwei andere Blöcke, nämlich das Thema Ressourcen. Und etwas zum Thema Property Property based Testing. Beides kann man halt auch in Verbindung mit 100 oder irgendwas anderem einsetzen. Und was ich halt durchaus weiß, dass es relativ viele gibt, die dann im Prinzip als Testframework drei Unit verwenden, dann aber durchaus die Essenz von Kotest und Ähnliches. Ja, aber es wird verwendet und soweit ich weiß auch relativ viel. Ja, aber erst mal noch mal zurück zum Thema Testframework. Was mir da sehr gut gefällt ist es bietet halt verschiedene Stile an, wie ich Tests schreiben kann. Also bei June ist es einfach mal so Du hast schreibst eine Funktion, machst du eine Test Annotation dran und dann ist das ein Testfall. Ja, genau. Und Annotations.
Sven
00:04:11
Die Java Annotation ist alles.
Benjamin
00:04:15
Also ich weiß nicht, das ist vielleicht schon mal ein bisschen angeklungen.
Sven
00:04:20
Haben wir noch nicht drüber geredet.
Benjamin
00:04:20
Dass ich nicht so ein großer Freund von Annotations bin. Bei Kotest ist es so, wie gesagt, es gibt verschiedene Stile und es läuft eigentlich immer darauf hinaus, dass man eine Testbeschreibung in irgendeiner Form als String hat. Also es ist nicht wie bei June, dass es die Funktion ist, der man dann einen Namen gibt, die irgendwie sagt was macht dieser Test? Sondern du hast einen.
Sven
00:04:39
Stimmt.
Benjamin
00:04:41
String und da schreibst du was.
Sven
00:04:43
Das ist das, was aus der Scala Welt kommt, weil da war das ja auch so gewesen. Ich schreib quasi einen langen String und der ist dann mein Testname.
Benjamin
00:04:50
Genau. Für mich hat es den Vorteil. Erfahrungsgemäß schreibt man da einfach, beschreibt man viel detaillierter, was dieser Test eigentlich macht, als man das macht, wenn man Funktionsnamen verwendet. Ja, was es dann auch noch gibt, ist immer die Möglichkeit, dass irgendwie so ein bisschen zusammen zu gruppieren auf verschiedene Arten. Das hängt dann vom gewählten Stil ab. Also wir verwenden da Funsbeck, da ist es letztendlich so, wenn man wirklich einen Test schreibt, dann ist das im Grunde ein Funktionsaufruf Test. Man übergibt als einen Parameter den Namen des Tests, also die Beschreibung, und als zweiter Parameter die Funktion, also das, was den eigentlichen Test ausführt. Und du kannst verschiedene solcher Testfälle dann immer noch in so einem Kontext Block schreiben, wo du dann halt auch noch mal was zusammenfasst. Ja, also das bietet sich sehr, sehr oft in Situationen, wo du halt sagst, okay, ich habe jetzt eine Funktion, die im Erfolgsfall macht, die das und das, im Idealfall macht sie das und das und dann kann man halt schon mal diese zwei Sachen Erfolg. Fehler durch den Kontext abgrenzen und hat dann da drin seine Testfälle ein bisschen gruppiert. Also es gibt einfach noch mal zusätzliche Struktur, was ich sehr, sehr angenehm finde und was es für mich auch sehr viel leichter macht, da dann am Ende auch irgendwie schön dokumentierte Testfälle drin zu haben, also mit einer ausführlichen Beschreibung.
Sven
00:06:10
Ich war. Wir sind unaufmerksam. Auf welcher Ebene findet diese Gliederung statt? Ich habe einen String, der beschreibt meinen Text. Dann gebe ich die Funktion rein und da drin verschachtelt ich noch mal, oder?
Benjamin
00:06:20
Das kannst du so machen. Das ist dann halt eine andere Funktion. Wie gesagt, bei dem Test, den wir haben, der eigentliche Test, das ist nur ein Aufruf einer Funktion, die Test heißt. Das ist nur ein Konstrukt von diesem Teststil, also von der Basisklasse, die man da verwendet. Und genauso gibt es eine Funktion Kontext und da gebe ich halt auch einen String rein und dann habe ich, ja, übergebe ich halt als zweites auch wieder eine Funktion rein. Also man hat dann natürlich nicht einen Parameter so mit zwei Aufrufen, sondern nicht man hat nur diesen einen Parameter und dann runde geschweifte Klammer auf und darunter den restlichen Code. Und unterhalb von Context kann ich halt weitere Kontextblöcke setzen oder Testfunktionen reinschreiben. Ja, es hat einfach nur so ein bisschen zusätzliche Struktur. Kann man in der Jugend auch machen, indem man nämlich in die Testklasse noch weitere Testklassen reinpackt, weitere Klassen, um dann darüber die Struktur zu kriegen. Wenn mich nicht alles täuscht, war es da in der Kombination für Kotlin dann immer noch notwendig, dass noch eine zusätzliche Annotation an den inneren Klassen war? Und ja, zum einen habe ich Annotations nicht sonderlich, zum anderen ich, ich. Für mich hat sich immer sperriger angefühlt, als dass dieses Konstrukt mit Kontext und Test und Ähnliches spielt natürlich auch eine Rolle. Genau das heißt von Scala Test gewöhnt bin und ja, was man gewöhnt ist und lange Zeit gerne genutzt hat, das will man dann natürlich weiter benutzen.
Sven
00:07:51
Wenn sich bewährt hat. Zumindest. Genau. Okay. Und warum will man überhaupt? Klar, du hast jetzt ja schon ein bisschen die Vorteile beschrieben, wie die Teststruktur ist. Das spricht natürlich schon dafür, für Kotlin was anderes zu nehmen, als einfach das zeichnet, dass es am Anfang auch gesprochen über die es war schon so und so. Dann kann man wahrscheinlich weiter hinten noch zu. Also was ist überhaupt der Auslöser was anderes zu nehmen als Zeit Unit? Einfach nur, weil man es schöner schreiben kann, sag ich mal?
Benjamin
00:08:18
Hm, also für mich war der Auslöser einfach in dem Fall wirklich das, was ich vorher bei Scala Tests gekannt habe. Dass ich dann halt in der Java Welt zurück war. Habe gesehen, wie es mit Religion aussah und dachte immer, das war aber schöner mit Scala Test. Und dann bin ich halt über Kotest gestolpert und habe das ja auch in dem anderen Team vorher dann mal vorgestellt. Und da hatten wir ja auch gesagt, wir verwenden das in Zukunft. Also der Auslöser bei mir war wirklich ganz massiv, einfach ich. Ich bin daran gewöhnt.
Sven
00:08:46
Und dann muss man dazu sagen Es ist natürlich immer schöner, eine Library zu nutzen, die nativ für diese Sprache entwickelt wurde, mit der ich arbeite, auch wenn andere Sachen gehen mit der Kompatibilität von der Kompatibilität her. Aber es macht halt einfach nicht so einen Spaß, wie wenn eine Library wirklich nativ für eine Programmiersprache entwickelt ist und dann auch die Möglichkeiten dieser Programmiersprache entsprechend nutzt. Wenn ich mich richtig erinnere bei Scala. Da konnte ich doch, glaube ich, direkt mit dem Stream anfangen. Da war das nicht, dass ich den Stream eine Funktion. Da gibt es ja bestimmt ne Extension Funktion bei Kotest, die genau das gleiche.
Benjamin
00:09:20
Genau. Genau das ist auch so und das ist halt auch ein bestimmter Stil. Und da kannst du halt auch genau das machen. Du schreibst String mit deiner Testbeschreibung und dann hast du irgendwie. Weiß ich nicht. Punkt. Punkt. Test? Keine Ahnung. Ich weiß es nicht. Darf es nicht verwenden. Kenne ich es nicht. Aber das ist halt genau einer dieser Tests. Die viele, viele andere sind dann halt auch einfach inspiriert von dem, was bei anderen Sprachen passiert, was in anderen Programmiersprachen üblich ist. Es gibt dann halt auch so einen Test Stil, der ist so vom Behavioral Driven Testing inspiriert. Da hast du dann so was wie ein wenn um, um das beschreiben zu können. Ich erinnere mich noch in der letzten Firma, die mit Scala Test angefangen hatten, da hatten wir sogar ursprünglich mal gesagt, diesen Stil verwenden wir für Integration Tests und den anderen für Unittests. Das hat sich da nicht wirklich bewährt und wir haben dann am Ende die ich glaube, wir Scala Test hieß sie tatsächlich auch Fansbeck, was wir jetzt hier verwenden, auch generell verwendet für alles.
Sven
00:10:23
Die andere ist wahrscheinlich einfach zu dogmatisch. Das klingt erst mal gut. Mit dieser klaren Struktur, die man da hat. Aber im Praxisalltag passt es halt einfach nicht immer. Aber.
Benjamin
00:10:32
Ja genau, es passt nicht immer. Du hast dann öfter mal Situationen, wo dir im Grunde ein Teil davon wurde, nicht sinnvoll angeben kannst. Und dann, wenn er dann plötzlich anfängt irgendwie was leer zu lassen oder irgendwas reinzuschreiben, weil man es machen muss, dann wird es auch einfach absurd.
Sven
00:10:47
Aber es heißt, am Ende ist es eigentlich egal, welche man nimmt. Das ist ein bisschen sind Taktik sogar, wie man so schön sagt. Das heißt, es geht einfach nur darum, wie sieht das aus, wie schreibe ich das Ding runter? Okay. Ja.
Benjamin
00:11:01
Zur zu dem was man schreibt als Test, Namen und ähnlichem. Auch noch eine Anmerkung. Ich sagte ja vorhin schon, ich weiß, dass es auch einige gibt, die dann 200 als Testframework verwenden und dann aber von Kotest die Slogans zum Beispiel. Und was ich dann auch schon viel gesehen habe, ist, dass dann Leute sagen Naja, was das Schreiben von Text angeht, da kann ich dann ja auch in Kotlin sagen, okay, den Funktionsnamen schreibe ich und dann kann ich da halt auch einfach Text schreiben, also auch mit Leerzeichen drin.
Sven
00:11:36
Achso, okay, weil ich Funktionsnamen immer packen kann bei Kotlin.
Benjamin
00:11:39
Genau. Genau. Genau.
Sven
00:11:41
Um Sonderzeichen unterzubringen. Ja.
Benjamin
00:11:45
Wer? Wer? Auch eine Option finde ich auch durchaus valide. Also wenn. Wenn jemand da so sehr an Jay gewöhnt ist wie ich, halt umgekehrt an diesen anderen Stil, dann kann man das auf jeden Fall auch machen. Damit kriegt man dann halt auch bessere Textbeschreibung Testbeschreibungen hin.
Sven
00:11:58
Wenn sich BTX nicht so schlecht schreiben lassen würden auf einer deutschen.
Benjamin
00:12:02
Genau. Genau. Ich.
Sven
00:12:02
Tastatur. Aber da habe ich ein Makro für.
Benjamin
00:12:05
Ich muss auch gestehen, ich habe mich da auch sonst nicht so wirklich mit anfreunden können. Es ist für mich. Fühlt sich irgendwie immer komisch an und man muss auch bedenken, man kann nicht jedes beliebige Sonderzeichen in diesem Funktionsnamen verwenden. Das ist in der Regel kein Problem, aber ich weiß noch, dass ich irgendwo mal was hatte, wo ich dann eben genau in der Beschreibung eigentlich ein bestimmtes Sonderzeichen drin haben wollte, was dann nicht ging. Ich glaube, es ist ein Slash oder ein Wechsel steht nicht oder so. Und wenn er da nun Testfall hat, der genau darauf geht und man ihm in der Beschreibung das schreiben will. Ja, man kann dann besser noch ausschreiben, kriegt man schon hin. Aber das Problem habe ich halt in dem String nicht.
Sven
00:12:45
Probleme, die die Welt bewegen.
Benjamin
00:12:46
Ja, ja, ganz, ganz, ganz gravierend. Was für mich dabei auch immer so ein Punkt ist, der dazu führt, dass ich ja da auch nicht so ganz begeistert davon bin, ist, dass es dann in der Regel so ist, wenn Leute es machen und deswegen gleich dazu sagen Ja, das würde ich in Produktivcode nie machen. In Testcode finde ich es okay. Und den Ansatz, den kann ich durchaus verstehen. Und ich mach auch öfter mal einen Testcode Sachen, die ich in Produktivcode so nicht machen würde. Aber so ganz grundsätzlich habe ich erst mal einen Test Code, den gleichen Qualitätsanspruch wie ein Produktivcode. Hintergrund ist ganz einfach Testcode hat sich in der Regel mindestens genauso oft an wie Produktivcode, oft sogar öfter. Und wenn dann der Testcode nicht wahrnehmbar ist, weil man zum Beispiel ganz viel immer dupliziert, statt es in Funktionen auszulagern, dann ist man irgendwann in der Situation, dass man sagt ich kann jetzt hier eigentlich den Produktiv Code nicht anpassen, weil ich dazu die Tests anpassen müsste und das ist zu aufwendig. Und deswegen finde ich halt immer so, diesen Ansatz zu sagen, das und das ist ein Testcode okay, aber ein Produktivcode nicht, den finde ich fragwürdig. Ich möchte nicht sagen, dass es falsch ist, das wäre zu dogmatisch. Es hängt immer auch vom Anwendungsfall ab. Ich finde es generell fühlt sich für mich immer ein bisschen komisch an.
Sven
00:14:02
Genau. Ja, kann ich bestätigen. Ich habe das früher auch mal so probiert. Also ich habe ja nie so viel Text geschrieben wie du. Weil mit der zu der Zeit, wo ich nicht mehr hauptberuflich entwickelt habe, da waren Tests noch gar nicht so populär. Und der größte Teil, den ich dann noch gemacht habe, war Freizeit Projekte. Aber ja, ich kenne es auch, dass ich am Anfang auch dachte, na ja, man schreibt ja quasi den Test einfach so runter und im Zweifelsfall dupliziert man den Code auch. Aber wie du sagst, das skaliert einfach nicht gut. Also hat man irgendwann keinen Bock noch mal das gleiche runter zu schreiben. Für Copy und Paste bin ich zu faul, weil da muss man immer viel hin und her scrollen und irgendwann lohnt sich dann einfach bestimmte Sachen wiederum in Funktion auszulagern. Was ich immer noch gut fand, war, wenn sich ein Testcase gut runterlesen lässt, also man gut versteht, okay, jetzt wird das getan, es wird das getan, es wird das getan und jetzt erwarte ich, dass das und das gegeben ist. Da finde ich, kann man auch Testcode schreiben, wo das nicht mehr so gut gegeben ist und dadurch schwer nachvollziehbar ist, was da eigentlich getestet wird.
Benjamin
00:15:07
Stimmt. Wobei das dann meiner Erfahrung nach meistens daran liegt, dass schon der Produktivcode nicht gut ist. Denn unübersichtlichen Testest Code vor allem dann, wenn du am Anfang wahnsinnig viel vorbereiten muss, damit der Produktivcode das machst, was er machen soll. Und das spricht dann oft dafür, dass entweder der produktiv Code schon zu komplex ist und man da vielleicht was aufteilen sollte in mehrere Funktionen, Klassen, was auch immer. Oder dass man gerade vielleicht auch im Test den falschen Scope hat und halt irgendwas testet, wo halt der Komplexitätsgrad viel zu hoch ist. Aber so was lässt sich nicht immer vermeiden. Grundsätzlich weiß ich, was du meinst. Ich finde es auch immer ganz gut, wenn man auch wirklich ganz klar erkennt hier wird vorbereitet, jetzt wird der eigentliche Test ausgeführt und da unten kommt das, was das Ergebnis sein soll. Also meine, meine Erwartungen, meine Versagens.
Sven
00:16:02
Ich hatte gelesen, bei Kotest gibt es auch das Konzept der Extensions. Was verbirgt sich da dahinter?
Benjamin
00:16:08
Ja, das ist in gewisser Weise so eine kleine Plug in Schnittstelle, dass man Sachen, also gerade wenn dann Sachen irgendwie sehr, sehr oft verwendet in verschiedenen Tests, kann man sich halt im Zweifelsfall seine eigene Extension dafür schreiben, um sagen zu können okay, ich ich häng jetzt nur an einer Stelle eine Klasse rein und dann passieren so ein paar Sachen einfach automatisch im Hintergrund.
Sven
00:16:29
Worum geht es also im Set Up und Clean up oder.
Benjamin
00:16:29
Ja, also ja, zum Beispiel, dass das kann eine Sache sein. Also es gibt auch einige fertige Extensions, die man nutzen kann, zum Beispiel für Testcontainer, wo man dann halt auch Hilfscode hat, um sagen zu können. Okay, ich starte jetzt irgendwie meine Datenbank in einem Docker Container, weil ich sie für den Test brauche. Also wir haben, das heißt wir haben unsere eigenen Extensions auch für Integration Tests geschrieben, wo wir dann halt auch dafür sorgen, dass bevor der allererste Integrationtest läuft auf jeden Fall alle Container die wir dafür brauchen, oben sind, und dass am Ende, wenn alle Tests durchgelaufen sind, halt auch alle Container gestoppt werden und dass im Zweifelsfall halt auf jeden Fall nach jeder Testklasse, also mindestens das die Datenbank geleert wird, so dass, jeder einzelne Test Klasse einen sauberen Stand hat. Und so was kann man ganz gut über Extensions lösen.
Sven
00:17:26
Wenn schon mal beim Thema Integration Test automatisch reingerutscht. Da wird man glaube ich später noch mal drauf kommen. Dann stelle ich mal meine Frage zur Performance noch zurück und denk hoffentlich noch genau dran.
Benjamin
00:17:38
Ja, ich kann ja versuchen, daran zu denken, dich zu erinnern. Es ist ansonsten generell so. Ich kann dir nur empfehlen mal auf die Dokumentation zu lesen, was was Kotest alles kann. Da sind halt noch eine ganze Menge Sachen mit dabei. Eine Sache, die ich immer ganz schön finde. Sie haben auch bei den Asiaten so ein Konstrukt, wo du halt sagen kannst, also du kannst in der Klasse selber sagen, in dem Test so Software und da verschiedene Sachen rein zu reinpacken und das führt dann dazu, dass so wenn mehrere davon fehlschlagen, alle ausgegeben ist und nicht immer nur die erste wie das wie.
Sven
00:18:13
Na okay.
Benjamin
00:18:14
Das heißt ganz klassisch ist. Das kannst du auch konfigurieren, dass das generell überall gehen soll. Dann sollte es in der Theorie so sein, dass man dieses als solche gar nicht braucht. Klappt in der Praxis nicht ganz. Da habe ich immer mal wieder Situationen, wo er dann doch nach der ersten Diskussion rausspringt.
Sven
00:18:31
Okay, so leicht ein Test so zu schreiben, dass der dann überhaupt weiter funktioniert. Weil wir sind ja schon darauf ausgelegt, die Testcases, dass wenn ich an der Stelle eine Session habe, also eine Bedingung nicht gegeben ist, dass dann die Bedingung danach gar nicht erfüllt sein können oder der Code nicht fortgeführt werden kann. Aber wie auch immer.
Benjamin
00:18:48
Das ist völlig richtig. Es kann trotzdem zusätzliche Informationen noch raus geben, wenn man alles kriegt. Weiß ich nicht. Konkretes Beispiel Ich schreibe einen Test, wo ich dann sage okay, der der Endpoint liefert mir jetzt ein Ergebnis zurück und der Status Code muss ein 200 sein und als Body muss der und der Text zurückkommen. Wenn ich da jetzt entsprechende sowas habe und ich habe eine Software und es kommen 400 zurück, dann kriege ich halt beide Sorgen und sehe dann am Ende auch der Body ist jetzt nicht das, was ich erwartet habe. Das ist ein wenig verwunderlich. Das würde mich dann sogar eher wundern, wenn trotzdem der erwartete Body kommt. Aber ich sehe vielleicht, dass da eine bestimmte Fehlermeldung zurückgekommen ist.
Sven
00:19:24
Guter Hinweis.
Benjamin
00:19:25
Ja, ähm, was da auch so eine Kleinigkeit auf den ersten Blick, die aber sehr nützlich sein kann. Du kannst bei uns immer noch ein uns darüber schreiben, wo du einen Text angibst und dann kommt halt die eigentliche Ressource dann noch in geschweifte Klammern dahinter. Das ist immer dann sinnvoll, wenn du irgendwelche Zahlen vergleichst oder du vergleichst den Wert. Und wenn man zum Beispiel als Rückgabewert true erwartet und es kommt sofort zurück, dann ist die Fehlermeldung, die du von dem Test kriegst, des true nicht gleich. Falls ist ja, wo ich halt sage Ja, stimmt.
Sven
00:19:58
Should have been true pathos falls.
Benjamin
00:20:03
Aber worum ging es hier eigentlich gerade?
Sven
00:20:04
Und das heißt, der Clou wird dann mit ausgegeben. Oder der Clou heißt ja.
Benjamin
00:20:07
Genau. Ja, ja, genau. Ganz genau. Und das muss sein.
Sven
00:20:08
Der wird damit ausgegeben, quasi als Hinweis, worum es hier gerade ging. Okay.
Benjamin
00:20:14
Darum muss man sich dann natürlich selber kümmern. Aber man kann es eben auch. Also, das sind so. So sehr, sehr viel Kleinkram, was einem dann an verschiedenen Stellen noch die Arbeit erleichtern kann. Bei dem bei den Associates, was du gerade als Beispiel gebracht habe irgendwas, bicht ist auch wieder eine Sache. Ich kenne es halt von Scala tests, wo es dann allerdings zusätzlich die Möglichkeit gab zu sagen Nee, ich möchte nicht schreiben, ich möchte Mastschreiben.
Sven
00:20:43
Ja, ich erinnere mich. Das war ein bisschen übertrieben, aber.
Benjamin
00:20:46
Ja, genau so im Rückblick betrachtet schon. Für mich führt es einfach auch da wieder dazu, dass der Testcode lesbarer ist. Zumal ich auch irgendwie. Ich habe so vage in Erinnerung, dass bei den Associates die dabei June Tests verwendet werden, wo man dann ja oft so was hat wie Escort Equills und dann halt zwei Objekte. Das ist für mein Gefühl immer das Set und aktuell vertauscht waren. Also ich weiß noch, dass ich fast jedes Mal davor saß und dachte Ach so, nee. Ja, ja, genau. Ach nee, muss andersrum sein, anders als ich es erwartet hätte. Das finde ich bei dieser Formulierung mit diesem Schutt, was auch immer, finde ich das irgendwie klarer. Ja, ich habe halt links das, was ich jetzt als tatsächliches Ergebnis habe. Genau. Und dann sage ich, das sollte so und so aussehen. Ja, und da gibt es dann auch eine große Bandbreite an Metaphern. Also man kann halt jetzt erst mal einfach auf Gleichheit machen. Man kann eine Kollektion darauf machen, dass sie eine bestimmte Zeit, eine bestimmte Größe haben, dass bestimmte Elemente drin sind. Man kann ja dann sogar so was sagen, wie darf nur die und die Elemente enthalten? Oder wenn man sagt okay, die und die müssen drin sein, ansonsten ist es mir egal, dann kann man auch das machen. Man kann sich auch auf die Reihenfolge festlegen. Also dass man sagt, das muss die Elemente in der Reihenfolge enthalten, wie ich das hier gerade angebe und Ähnliches. Und man hat natürlich auch da die Möglichkeit, seiner eigenen Natur zu schreiben. Was gerade wenn sich bestimmte Vergleiche in mehreren Testklassen immer wiederholen, sehr, sehr angenehm ist. Und auch da wieder zu sehr lesbaren Code führen kann.
Sven
00:22:33
Und ich sehe hier in deinen Notizen, dass man auch ohne Punkte schreiben kann. Das ist dann ja wahrscheinlich einfach Kotlin Syntax. Resultat 42 ohne Punkte. Dann hätte ich auch noch wie damals bei Scala damit auch herumhantiert haben, wo es dann ja so bestimmte Konstellationen gibt. Wenn eine DSL Botnet Domains language, dass man dann zwischen bestimmten Aufrufen doch wieder Punkte haben muss. Frage mich im Nachhinein auch, ob man da nicht manchmal mehr Zeit vergeudet, damit es irgendwie ein bisschen hübscher im Code aussieht, als es der Realität was bringt.
Benjamin
00:23:05
Also in dem Fall ist es bei Kotlin ist es da auch noch ein bisschen einfacher. Man kann es nicht unter bestimmten Bedingungen machen. Letztendlich ist es relativ klar, Die Funktion, die man da aufruft, muss als Fixfunktion definiert sein. Bedarf sind natürlich nur einen Parameter haben, sonst klappt es auch wieder nicht. Man.
Sven
00:23:22
Na? Aber könnte ich dahinter noch eine Funktion jetzt stecken?
Benjamin
00:23:26
Also, wenn du das machen will.
Sven
00:23:27
Also res, also die Partitur weiß nicht end.
Benjamin
00:23:32
Nee, nee, geht an der Stelle nicht. Was man dazu auch sagen muss ich persönlich bin irgendwie gerade bei diesen Tests bin ich enorm daran gewöhnt, das ohne Punkt und ohne die Klammern zu haben. Ich finde es einfach viel lesbarer. Ist aber natürlich auch Gewohnheitssache. In der Entwicklungsumgebung für die Entwicklungsumgebung ist es tatsächlich so, dass die damit besser klarkommt, wenn man die Punkte schreibt und die Klammern setzt. Also das führt jetzt nicht dazu, dass man plötzlich Fehler angezeigt bekommt, aber es belastet die CPU ein bisschen mehr. Wenn ich jetzt auf mal merke, ich jetzt auf meinem Rechner auch nicht. Ja, das habe ich mal in einem Vortrag erzählt, dass mal einer. Ich hatte es dann mal ausprobiert und dachte okay, gut möglich. Das war allerdings noch mit meinem alten Mac. Ich habe da jetzt bei dem neuen nie was gemerkt, aber es hat durchaus was, wenn einem da die Performance enorm wichtig ist und man hat das Gefühl, das Ganze wird sehr langsam, dann kann sich in den Tests einfach mal lohnen zu sagen, ich schreibe jetzt über all die Punkte und setze die runden Klammern dann, dann ist es besser.
Sven
00:24:33
Wahrscheinlich brauchen Sie ein bisschen mehr Kontext an der Stelle, um das sinnvoll auswerten zu können.
Benjamin
00:24:38
Keine Ahnung. Ich kann es mir schon vorstellen, dass das ein bisschen aufwendiger ist, diese ganzen möglichen Variationen. Aber.
Sven
00:24:45
Und du sprachst eben schon von Erweiterung. Das gibt es auch für Sessions.
Benjamin
00:24:52
Auch da ist was, was wir da ganz explizit nutzen. Sind halt Erweiterungen für, Kater, weil es halt unser Hauptframework ist, wo dann halt so Sachen machen kannst wie Also du hast ein Request get, das getestet ist, dann sagst du, es ist schon etwas Status, 2:00 null und dann guckt er eben wirklich in das Ergebnis rein, wo dann was was hat ja irgendwie ein komplexeres Objekt ist. Holt sich den Status raus, vergleich den und Ähnliches. Ja, aber.
Sven
00:25:21
Was vielleicht noch interessanter für den Inhalt, weil.
Benjamin
00:25:24
Ja, ja, ja, da kannst du durchaus auch was machen. Da wird es dann schon potenziell ein bisschen komplizierter, weil er dann ja im Zweifelsfall wissen müsste, was ist das jetzt eigentlich? Ist das ein Jason oder ist das einfach nur ein String? Ja, aber es gibt halt eine ganze Menge, was man da machen kann. Und ja, es ist wie gesagt auch wirklich kein Problem, seiner eigenen Natur zu schreiben. Ja, habe ich auch schon mehr als einmal gemacht ist.
Sven
00:25:48
Gibt es da auch was für Asynchronität? Das ist ja auch so ein Problem, was man in der realen Welt manchmal hat, dass man halt Sachen testet, die einen Gott, wie ist es denn bei Kotlin? Ich bin voll in TypeScript Welt unterwegs dienen Promise zurückgeben oder wie auch immer das da heißt.
Benjamin
00:26:02
Also das Problem haben wir so ja nicht, weil das ja alles über Korothins läuft und die Tests auch in einem Core-Team Kontext laufen. Von daher hat man das nicht.
Sven
00:26:07
Okay.
Benjamin
00:26:13
Aber es gibt da durchaus auch so Sachen. Das gehört jetzt gar nicht so sehr zu den Ressourcen, sondern eher zum Testframework, wo du auch so Aktionen machen kannst wie, also bei machen dann eventuell die und dann wird halt auch mit einem bestimmten Timeout, was du auch angeben kannst, auf irgendwas gewartet und wenn es dann nicht passiert, dann gibt es aber auch einen Fehler und wenn es bis dahin passiert. Also habe ich mir jetzt, um ehrlich zu sein, auch noch nicht im Detail angeguckt.
Sven
00:26:38
Weil wir es einfach nicht brauchen.
Benjamin
00:26:38
Es für uns nicht so weit, nicht so relevant ist. Aber da geht schon auch einiges.
Sven
00:26:45
Was ja immer spannend ist, ist das Thema Testdaten. Wie man damit umgeht. Wo kommen die her? Das ist ja gefühlt irgendwie das, was bei den Tests auch am meisten Aufwand macht, den Kram zu entwickeln. Überhaupt das misst fand ich immer das, was lästig war. Aber bei mir war mal so richtig ein Aufatmen, wenn dann dann die Testdaten gebaut hat. Jetzt kann ich endlich den Test schreiben, den ich haben will.
Benjamin
00:27:09
Also erst mal dann noch ein Schritt davor. Was bei Kotest auch sehr gut geht, dass man ein und denselben Test für verschiedene Testdaten ausführt. Ist jetzt auch sonst keine große Sache. Im Zweifelsfall hat man halt eine Funktion, die man dann halt mehrfach aufruft in einer Schleife. Bei Kotest ist es dann immer so, dass man zu einem Kontextblock dann eine Funktion, zum Beispiel über Data, da gibt es auch noch ein paar Variationen, da schreibt es als Parameter einen Testdaten rein und dann dahinter der Test, der ausgeführt wird. Kotest versucht dann immer, aus den Testdaten noch einen Namen zu generieren, so dass es dann in der Ausführung am Ende so aussieht, als hättest du wirklich, für jedes Datenobjekt, was du da reingibst, einen Test selber geschrieben, also manuell eine Testfunktion geschrieben, die dann immer das gleiche macht.
Sven
00:27:57
Das heißt der Testname setzt sich dann aus den Daten und wie gut klappt das so?
Benjamin
00:28:03
Wenn es eine Data Class ist, ganz gut. Ansonsten ist es immer sinnvoll, sich selber was zu schreiben, was man aber eben auch kann. Also ich kann dann in Numbers Data Blog als erstes eine Funktion angeben, die mir aus dem aktuellen Datenobjekten Testnamen generiert.
Sven
00:28:15
Wie macht er das auch bei Big Data? Klar ist das holt sich dann einfach die.
Benjamin
00:28:18
Am besten, er ruft einfach zu String auf, würde ich mal vermuten.
Sven
00:28:19
Property und den Wert, auf den sie gesetzt ist und bildet daraus was. Naja, okay, gut. Okay. Also ist jetzt kein sprachliches Wunderwerk. Dann an der Stelle. Gut.
Benjamin
00:28:27
Nein, nein, nein. Ja und ansonsten zum Generieren von Testdaten. Da haben wir halt auch als getrennt verwendbares Artefakt das Property React-testing. Da gibt es jede Menge Klassen, um sich zufällig Testdaten zu generieren. Also da kann man halt so Sachen machen. Jetzt ganz simpel und primitiv. Ich brauche ein bisschen Wert, also gib mir mal einen. Da kann man sich noch vorstellen, dass das relativ einfach ist, seit er drei oder vier ist. Man kann dann aber auch zu sagen ich brauche jetzt eine Zahl zwischen eins und 512, oder ich brauche einen String, der soll zwischen zehn und 500 Zeichen lang sein und aus den und den Zeichen bestehen. Ja, es gibt da dann auch noch die Möglichkeit, man kann über so ein bestimmtes Interface sich dann noch selber Generatoren für eigene Testdaten schreiben, wenn man halt komplexere Objekte hat, wo dann halt auch letztendlich irgendwie mit zufalls generierten Daten Felder befüllt werden. Und was ganz nett ist, dieses Interface bietet dann immer noch eine Funktion Case, wo man halt, wenn das sinnvoll möglich ist, für dieses Objekt praktisch sagen kann okay, das das ist so ein Fall, so ein Sonderfall, der könnte eventuell Probleme bereiten. Von daher.
Sven
00:29:47
Den nimmt er dann immer rein, oder?
Benjamin
00:29:50
Naja, nicht unbedingt. Es kommt ja dann darauf an, was du mit diesem Generator machst. Im Zweifelsfall ist so ein Generator Objekt und dann soweit okay, ich brauche jetzt noch einen Wert und dann kriegst du einen.
Sven
00:30:00
Okay. Okay, gut.
Benjamin
00:30:01
Und das kann dann dieser okay sein. Der muss es aber nicht sein.
Sven
00:30:04
Das heißt, wenn ich wirklich den Test mit vielen unterschiedlichen Daten laufen lasse, dann muss ich mich immer noch selber darum kümmern, dass ich da eine Schleife aufmache und sage das, was ich jetzt 100 Mal mit 100 zufälligen Werten.
Benjamin
00:30:15
Warum ist das so? Sich nicht selber kümmern. Da gibt es dann auch noch zu den Generatoren in dem zugehörigen Kompendien Objekt eine ganze Menge Hilfsmethoden, unter anderem eine List, wo du dann Generator eingibst und sagst Ich möchte jetzt. 100 bis 1000 Objekte davon haben und dann generierte die entsprechende Liste, die du dann in deiner Funktion mit rein nimmst. Es gibt dann da auch zusätzlich noch die Möglichkeit. Das kann man natürlich nicht mit allem machen, dass du zum einen sagen kannst okay, ich möchte jetzt hier was machen mit einigen der möglichen Werte oder mit allen der möglichen Werte. Also bei Berlin kannst du was machen. Wenn es jetzt geht um eine ganze Zahl zwischen eins und 100 kannst du auch noch mit allen machen.
Sven
00:30:57
Beim Thema Western.
Benjamin
00:30:58
Beim Integer wird es schwer, oder auch wenn nur ein String von 1 bis 100 Zeichen hast. Ja, das kriegt man schon auch noch hin. Abhängig von der verwendeten Zeichenzahl wird es dann schon auch echt heftig. Ja, aber es ist schon enorm gut, was man da alles machen kann, um sich einfach Testdaten zu generieren. Und zwar vor allem auch einfach Daten zu generieren. Die, die dann irgendwie sind. Wenn man selber sich Daten schreibt, dann hat man in der Regel die Situation, dass man immer wieder die gleichen Namen verwendet usw. Und da sind dann vielleicht bestimmte problematische Konstellationen gar nicht drin und man findet vielleicht irgendwelche Fehler nicht.
Sven
00:31:40
Hmm. Muss ich mir für Data Classes immer eigene Generatoren schreiben oder gibt es auch so Mechanismus, dass ich sage hier für die Klasse generiere mal was? Weil eigentlich enthält die Klasse ja alle Informationen, da ist dann String drin, der ist optional, das heißt da weiß er, da kann er mal, ist nicht gesetzt rein setzen, kann aber auch Strings durchprobieren. Dann gibt es hier noch was weiß ich, Alter als Zahl, um jetzt mal eine Person abzubilden, dass es eben verschiedene Permutationen durchrechnet. Oder muss ich mir da für den eigenen Generator, wo ich dann jedes dieser Felder quasi enttäuschend.
Benjamin
00:32:10
Schon selber machen. Ich. Ich meine, ich würde an der Stelle auch sagen, ganz so einfach wie du das gerade geschildert hast, ist es nicht.
Sven
00:32:17
Wahrscheinlich nicht. Ich habe es nicht durchdacht.
Benjamin
00:32:18
Naja, letztendlich, man könnte das schon machen. Die Frage ist, ob es fachlich sinnvoll ist, denn du kannst ja nicht unbedingt am Feldnamen erkennen, dass die Zahl jetzt ein Alter ist und dass es deshalb nicht sinnvoll ist, da eine 500 rein zu generieren.
Sven
00:32:33
Passiert in der Realität vielleicht auch von daher. Es kann ja bei zufällig.
Benjamin
00:32:35
Ja.
Sven
00:32:36
Generierten Daten genau der spannende Fall sein.
Benjamin
00:32:38
Ja, also es ist halt. Ich denke, es ist einfach zu schwierig. Ist es dann schon sinnvoller, selber raufzugucken und auch zu sehen, Was brauche ich hier konkret für Testdaten? Aber es ist auch so bei dem, was Kotest am mitbringt, dass da eine ganze Menge Spezialitäten auch noch mit drin sind. Du kannst jetzt zum Beispiel Vor und Nachnamen generieren lassen. Ja, dahinter steckt dann irgendeine Liste. Also das ist dann da. Da merkt man auch, dass es aus den USA kommt. Das sind glaube ich nur englische und spanische Namen.
Sven
00:33:08
Okay.
Benjamin
00:33:08
Aber im Zweifelsfall kann man die kannst du da auch sagen, Nimm bitte diese Liste und kannst deine eigenen Listen generieren. Domäne werden dann zufällig generiert.
Sven
00:33:18
Also ich sage jetzt mal Sabbat um eins. Also, okay.
Benjamin
00:33:22
Ja, genau. Genau. Ja. Dann hast du so Sachen wie die Flughafencodes. Also bar kriegst du dann raus. Und das sind auch alles real Existierende. Dann gibt es auch einen Haufen Sachen aus der Kategorie. Ich weiß nicht, wofür man das braucht. So Eissorten. Londoner U Bahn Stationen?
Sven
00:33:41
Ist auch Schlumpfeis bei.
Benjamin
00:33:43
Keine Ahnung. Ich habe es nicht ausprobiert. Wie gesagt, Londoner U Bahn Stationen. Und ich glaube, da gab es dann sogar eins, wo man sich halt Wege von Station.
Sven
00:33:47
Aber.
Benjamin
00:33:52
Zu Station zu anderen Stationen ausgeben lassen konnte. Ja, Verdächtige aus Cluedo. Cluedo, Mordwaffen.
Sven
00:34:01
Es klingt irgendwie, als wenn da ein paar Leute Langeweile hatten.
Benjamin
00:34:04
Ja, ich. Ich denke, das war dann auch was, als dieses Grundkonzept da war Und so ein paar Harry Potter Charaktere sehe ich hier gerade.
Sven
00:34:11
Na gut, das macht wieder Sinn.
Benjamin
00:34:12
Ähm, ja. Was ich auch interessant fand, so Schachfiguren, Schachfelder und dann als logische Konsequenz daraus Schachzüge.
Sven
00:34:19
Sachzwänge? Nein.
Benjamin
00:34:21
Allerdings ohne Validierung, ob die gültig sind. Aber trotzdem ist schon einfach eine sehr, sehr schöne Sache. Ich glaube, das sind im Zweifelsfall Sachen, die guckst du dir mal an, wenn du vielleicht selber irgendeinen speziellen Fall hast und denkst Ja, wir haben ihnen das gemacht. Ja, aber es ist so. Da geht echt wahnsinnig viel. Und. Ja. Ich fand es extrem hilfreich. Bei uns schon. Das hat uns das Generieren von Testdaten sehr, sehr einfach gemacht, weil wir an vielen Stellen uns einfach überhaupt keine Gedanken machen, sondern dann irgendwo sagen Ja, wir haben hier ein Feld, das enthält ein String und wir wissen, der muss mindestens ein Zeichen, maximal 255 lang sein. Also generieren wir uns dafür einen und machen uns auch keinen großen Kopf, ob das, was dabei rauskommt, wirklich sinnvoll ist. Nicht. Also bei Vorname macht es eigentlich nicht wirklich Sinn, wenn man so viele Specials, Slash, geschweifte Klammern und so was mit getestet werden. Aber es schadet auch nicht. Wer weiß, was die Leute da eingeben.
Sven
00:35:22
Genau der Punkt. Es geht ja gerade genau auch darum, die Fälle abzudecken, die irgendwann mal irgendjemand eingeben könnte, weil das sind genau die Dinge, die man nicht auf dem Schirm hat. Und sag mal, wie ist es mit der Bei jedem Test Durchlauf werden dann andere Daten generiert. Das heißt im positiven Fall heißt es, ich teste viel ab. Im negativen Fall heißt es aber auch, dass der Test noch durchgelaufen beim nächsten Durchlauf ist. Schlägt viel.
Benjamin
00:35:45
Also hängt davon ab, was man macht. Im Endeffekt werden die Testdaten halt zufällig generiert, das heißt irgendwo hat man random mit drin und das wird mit generiert und das kannst du auch selber setzen. Wir hatten es bei uns ursprünglich mal so, dass wenn wir ein festgelegtes, festgelegten Set Wert hatten, was bedeutet.
Sven
00:36:06
Das heißt dann generiert er reproduzierbar zwar zufällig, aber reproduzierbar immer die gleiche Zufallsfolge.
Benjamin
00:36:09
Genau, genau. Was allerdings auch nicht ganz so prickelnd war, weil wir dann zum Teil die Situation hatten, dass wenn ich ein Test einzeln ausgeführt habe, ist er durchgelaufen. Wenn ich alle Tests zusammen ausgeführt habe, ist er nicht durchgelaufen, weil dann andere Daten generiert wurden.
Sven
00:36:23
Weil weit mehr generiert wurde und dadurch.
Benjamin
00:36:25
Genau. Genau. Und dann hast du halt sofort auch die Situation, dass das eben nicht mehr wirklich reproduzierbar ist. Inzwischen ist es so, dass wir als sieht das das gleiche Problem. Ich will da auch gerne noch mal was ändern, dass wir jetzt einfach die aktuelle Zeit nehmen, wo mit Zeit schon noch mal zufälliger wird, weil halt bei jedem Test wirklich was anderes verwendet wird. Was ich da schon mal gelernt hatte, ist das Kotest da eigentlich. Wenn man dann noch die Tests anders schreibt, als wir das aktuell machen, von sich aus die Möglichkeit sofort mitbringt zu sagen okay, wenn ein Test fehlschlägt, dann schreibe ich für diesen Test, Das geht auf die Festplatte. Also wird eine Datei geschrieben, auch mit dem Testnamen. Und da steht dann drin, was für ein Set wurde verwendet für diesen Test. Und wenn er dann den Test noch mal ausführt, wird das aus der Datei verwendet. Und damit kriegt man in dem Moment dann auch genau die Test, also die generierten Testdaten, die zu dem Fehlschlag geführt haben. Das heißt, gerade wenn ein Test fehlschlägt und das wegen Testdaten sehr, sehr hilfreich, weil man dann kann sich das dann genau angucken und dann versteht hoffentlich irgendwann, warum der Test fehlgeschlagen ist. Kann man es fixen, kann es dann noch mal ausführen und weiß dann okay, das Problem, was jetzt diese Testdaten gebracht haben, das gefixt, das habe ich nicht mehr.
Sven
00:37:45
Und das macht dann automatisch, wenn man es entsprechend konfiguriert hat, in den Fällen, wenn ein Test fehlschlägt. Hm, okay. Und sag mal, wie ist so deine Erfahrung damit? Ich fand zwar das Schreiben der Testdaten immer anstrengend, aber dafür haben sie irgendwie den Vorteil gehabt. Wenn ich dann, wenn da mal ein Test fehlgeschlagen ist, dass ich schon anhand der Daten häufig wusste, worum es geht, weil die Testdaten quasi von Hand erstellt waren und dann war halt mein Martin Schulz und dann hat er halt nicht den richtigen User gefunden. Das ist ja hier dann ein bisschen schwieriger, weil man keinen persönlichen Bezug zu den Testdaten hat, sondern die sind halt einfach irgendwas Abstraktes.
Benjamin
00:38:22
Das ist auf jeden Fall schwieriger. Ich finde es aber auch nicht so wild. Also es hat mich bisher noch nie wirklich gestört. Im Zweifelsfall sind es dann manchmal Situationen, wo es sich halt auch einfach lohnt, noch irgendwo einen Club oder so was einzubauen, dass man halt selber noch mehr Informationen kriegt.
Sven
00:38:36
Den Kontext besser hat, wo was schief gelaufen ist.
Benjamin
00:38:38
Und genau und dann eher versteht, Aha, dass es an der und der Stelle. Richtig schwierig finde ich es immer, wenn man dann Kollektion vergleicht und ich dann halt irgendwo eine Liste mit 20 Elementen habe und davon ist eins falsch. Da wird es dann einfach unübersichtlich. Aber da ist es auch einfach völlig egal, in welchem Kontext das passiert. Ob ich da mit generierten Testdaten oder selbst erstellten arbeite, spielt keine Rolle.
Sven
00:39:03
Und stell mir gar nicht mehr selber. Also läuft das alles über diesen Mechanismus oder gibt es da bestimmte Anwendungsfälle, wo man sagt da stehe ich doch von Hand?
Benjamin
00:39:10
Wir erstellen doch von Hand an einigen Stellen. Also konkretes Beispiel Wir hatten an irgendeiner Stelle einen Test, da haben wir Daten in die Datenbank geschrieben und dann haben wir geguckt, dass die in der erwarteten Reihenfolge zurückkommen.
Sven
00:39:24
Klar.
Benjamin
00:39:24
Ja erwartet. Reihenfolge mit zufällig Testdaten läuft dann darauf hinaus, dass man da dann am Ende für die Testdaten im Code noch Kotlin sortieren lässt. Das Dumme ist nur, dass Kotlin anders sortiert als die Datenbank und wir damit keinen zuverlässigen Test hatten. In solchen Situationen ist es dann definitiv besser, dass ich sage, ich schreibe mir selbst meine Testdaten, damit ich halt auch persönlich sagen kann, das ist die Reihenfolge, die ich erwarte und die teste ich dann.
Sven
00:39:54
Kann ich auch so was machen, wie um mir diesen lästigen ich schreib die händisch selber Fall zu entgehen, dass ich sage okay, ich lass mir die generieren übernehmen. Das generierte dann in Code, das heißt ab da sind es feste Daten. Aber ich muss mir nicht diese initiale Überlegung, in den ich den Nutzer jetzt was hatte für eine Emailadresse, bei welcher Firma arbeitet er, um mir diesen diesen Kram zu ersparen? Wobei man da bestimmt auch was generieren kann inzwischen, was man rein testen kann.
Benjamin
00:40:24
Habe ich, um ehrlich zu sein, noch gar nicht passiert. Ich wüsste aber nicht, er probiert. Ich wüsste nicht, warum es nicht funktionieren sollte. Im Zweifelsfall müsste man sich ja ein kleines Kotlin Skript dafür schreiben, was dann die Testdaten generiert und irgendwie ausgibt, dass man dann gut damit arbeiten kann. Also von daher.
Sven
00:40:41
Na siehste, ist sein Freund. Habe ihn gerade mal gefragt. Generiere Testdaten als Jason für eine Person. Und dann hat er mir einen Jason rausgehauen, was ich direkt rüberkopieren könnte. Jetzt für drei Personen. Ja okay, macht er natürlich auch anstandslos und dann kann man ihm bestimmt noch vorher eine Deklaration der Klasse reingeben. Und dann hätte man das Problem.
Benjamin
00:41:04
Und dann sich den ganzen Text selber schreiben lassen.
Sven
00:41:07
Und dann sich den Tesla schreiben lassen. Ja, genau. Ja, genau.
Benjamin
00:41:08
Also bzw. ihn schreiben lassen.
Sven
00:41:11
Also eigentlich die Anweisung des CPT. Teste verdammt noch mal diesen Code. Ja.
Benjamin
00:41:17
Ich weiß nicht, aber gut.
Sven
00:41:21
Okay, gut, das passt zum Thema Testdaten. Genau. Finde ich auch immer spannend. Und jetzt gibt es natürlich noch die spannende Frage, wo es ja auch religiöse, Ungereimtheiten oder religiöse Meinungen zu gibt. Wie geht man eigentlich mit Macken um?
Benjamin
00:41:40
Hm, also dazu zuerst mal zwei Ansichten, die ich schon in der Vergangenheit gehört bzw. gelesen habe. Das eine ist, da war ich mal bei den Scala Days in einem Vortrag von dem Autor von Scala Test. Und da kam von irgendjemandem eine Frage zum Thema Morgen relativ zum Ende. Und als ich rausging, hörte ich, wie ein Entwickler zu einem anderen Thema wahrscheinlich zusammen da war, sagte. Ich sage ja immer, wer mobbt, ist nur zu faul seine Testdaten aufzusetzen. Finde ich eine ziemlich radikale Bemerkung. Ich persönlich würde ja sagen, wer nicht mobbt, testet seine Logik nicht richtig. Das ist mit Sicherheit genauso radikal und in der Allgemeinheit auch genauso falsch wie die andere Aussage.
Sven
00:42:27
Eigentlich geht es ja auch gar nicht um Faulheit. Ich meine, bei mir geht es ja einfach darum, gerade bei Tests Sachen raus zu halten, die ich gerade gar nicht testen will. Zum Beispiel eine Datenbank, wenn ich ein DAO teste. Das hat ja nichts mit Faulheit zu tun, denn.
Benjamin
00:42:38
Damit kommen wir zu dem zweiten Zitat, was ich bringen wollte. Ich hatte kürzlich irgendwo auch was. Da habe ich, glaube ich auch noch irgendwas zum Thema Mobbing gesucht. Und da bin ich auf einen Artikel gestoßen, wo der Autor dann meinte, in Unittests sollte man gar nicht merken, wenn überhaupt. In ausgewählten Fällen in Integration Tests, wo ich davor saß und dachte nee, sehe ich genau umgekehrt.
Sven
00:43:00
Also wenn wir es genau andersrum sehen.
Benjamin
00:43:02
Ja, also erst mal als Technologie. Wir verwenden MOOC, dass es da auch wieder, im Grunde der Punkt, den ich vorhin schon brachte es ist halt in Kotlin geschrieben, ist es für Kotlin gedacht und da gehen einfach auch Sachen, die man mit Mojito oder so nicht hinkriegt, vielleicht inzwischen schon. Da die Kotlin ja relativ weitverbreitet ist, gibt es da natürlich auch von anderen Frameworks. Dann immer noch Nacharbeiten, aber. Also ich persönlich bin da auch sehr glücklich. Da geht eigentlich immer alles, was ich machen will und das auch sehr gut. Und was machen wir ohne Tests und Integrationtests? Gar nicht. Und bei Tests ist es halt auch so In Unit Tests merken wir halt quasi die darunterliegende Ebene, also das, was du gerade schon sagtest, Wenn ich einen Service teste und der verwendeten DAO, dann ist das Thema Datenbank Zugriff. Und so ist für mich in dem Moment gar nicht im Scope, sondern ich. Ich möchte ja eigentlich genau testen Macht der Service das, was ich erwarte, wenn vom DAO ein bestimmtes Ergebnis kommt? Und klar, da kann ich mich natürlich auch hinstellen und sagen, ich schreib jetzt die Testdaten, die ich dafür brauche, in die Datenbank und, dann habe ich das Ergebnis auch.
Sven
00:44:19
Definitiv kein Unittest mehr.
Benjamin
00:44:20
Dann ist es für mich auch kein Unittest, dann ist es ein Integration Test. Ich brauche die Datenbank dazu. Ich teste das DAO mit, was ich eigentlich eher getrennt testen will. Außerdem muss man halt sagen, ist es erfahrungsgemäß sehr sehr schwer alle theoretisch möglichen Fehler Situationen nachzustellen, Denn im Zweifelsfall macht man sich dann beim Code schreiben plötzlich auch Gedanken. Ja, was ist denn, wenn jetzt hier mit einem Request die Datenbank wegfliegt? Vielleicht unrealistisch, unwahrscheinlich, aber auch nicht ausgeschlossen. Und dann baut man vielleicht irgendwas dafür ein. Ich erinnere mich noch in der letzten Firma, wo wir uns dann auch noch darum gekümmert haben, Code zu schreiben, der dafür sorgt, dass genau wenn die Datenbank wegfliegt, das eben auch ohne Neustart der Anwendung auf jeden Fall die Verbindung wiederhergestellt wird, wenn die Datenbank da ist. Da hatten wir ursprünglich mal Tests, dann zwei Datenbanken und ich habe versucht, dieses, dieses Szenario, sie fällt aus und er verbindet. Sich Danach neu nachzustellen ist mir einfach nicht gelungen. Und.
Sven
00:45:21
Und hätte dann nichts zu tun mit dem realen Datenbankserver.
Benjamin
00:45:23
Genau und sowas sind halt einfach Situationen, wo ich sage, da kann ich in June Tests. Wenn ich halt die Ebene da drunter gemobbt habe, kann ich alle Fehler, die ich da irgendwie testen will, kann ich problemlos einfach durch das Mock nachstellen. Ja, wenn ich da wirklich dann gleich den Integrationstest mache, in dem ich halt wirklich das darauf folgende und die Datenbank dahinter, ist das viel, viel schwieriger bis hin zu unmöglich.
Sven
00:45:47
Das heißt, da werde ich dann andere Sachen testen als beim als beim Unittest beim Unittest funktioniert, teste ich die Funktionalität des Services. Die Fachlichkeit sage ich mal und beim Integrationtest teste ich dann noch ein, zwei spezifische Fälle, um mal zu prüfen, ob der ganze SDK in sich funktioniert.
Benjamin
00:46:07
Also es ist aktuell bei uns auch so, dass wir für DAOS tatsächlich nur Integration Tests haben, weil wir da keine Logik drin haben, sondern nur Datenbankabfragen.
Sven
00:46:16
Es wäre auch Quatsch, da zu fragen Ist jetzt das und das SQL Statement rausgekommen? Ja, es ist auch irgendwie spannend, aber meistens ist es da auch so dumm, dass da nicht so furchtbar viel Logik drin ist. Und dann macht es nur Sinn, das auch wirklich mit einer Datenbank zu testen.
Benjamin
00:46:29
Ja eben. Und da haben wir halt auch von der Version die gleiche, die wir in der Produktion einsetzen. Nein, stimmt gerade aktuell nicht. Da müssen wir mal updaten. Aber das ist eigentlich das Ziel. So ist man halt. Da testen wir gegen das, was wir auch in der Produktion verwenden. Und ja, damit haben wir da auch eine gewisse Sicherheit, dass es so läuft, wie wir es haben wollen. Ja, aber auf DAO Ebene haben wir wirklich nur Integration Tests darüber. Also sowohl für die Services die wir haben, als auch für die die End Points, also die die Controller da in gewisser Weise. Da haben wir auch Integration, Unittests. Das geht ja auch ganz gut, dass man dann halt wirklich sagen kann, ich habe. Ja keinen echten Server, der ja hochgefahren ist, aber halt schon so ein bisschen was, das auch wirklich die Requests simuliert werden und dann halt entsprechend weiterverarbeitet werden. Wie das in der Realität auch passiert. Und dann kann ich halt schön abtesten, dass ich halt auch das erwartete Ergebnis zurückbekomme. Ja, und dann haben wir halt zusätzlich auch auf der Controller Ebene noch mal Integration Tests, wo wir dann halt auch noch mal wirklich die komplette Kette durchgehen, also vom Requests bis zur Datenbank und wieder zurück. Abhängig vom Request prüfen wir dann auch durchaus noch mal, dass auch in der Datenbank das passiert ist, was wir erwartet haben. Und ja, da ist es dann aber so, dass wir jetzt nicht mehr versuchen, jeden Fehler nachzutesten. Sagen wir halt also, für das, was der Service da Spezielles macht, haben wir die Unittest vom Service. Für das, was ihm da so passieren kann, haben wir die Integration Tests vom DAO, sondern da haben wir so die Philosophie, Happy Pas und vielleicht noch so ein, zwei zusätzliche Sachen, aber das war's dann auch.
Sven
00:48:08
Aber das heißt bei Integration Tests haben wir durchaus auch mehrere Ebenen. Also du sagst, ihr testet sowohl den DAO als auch vom Controller aus, also vom REST-Endpoints aus. Das haben wir schon. Beides.
Benjamin
00:48:20
Das haben wir schon ein weiteres Jahr. Denn wie gesagt, in den da wo ich die die Endpoints teste, da möchte ich dann nicht mehr irgendwelche Spezialitäten, die im DAO auftreten können, testen. Das mache ich halt in einem Integrationtest für DAO. Könnte man natürlich auch zusammenfassen. Ich finde es so ein bisschen besser, weil ich dann halt auch bei einem Fehler im Zweifelsfall genauso. Ja, das ist jetzt kein Problem da so und nicht an einer anderen Stelle.
Sven
00:48:45
Wie sieht es bisher mit der Performance bei den Integrationtests aus?
Benjamin
00:48:52
Man darf sich da keine Illusionen machen. Integrationtests sind immer ein bisschen langsamer als die Tests, wobei wir da ein paar Sachen auch gerade noch ungünstig machen. Da sind wir noch auch selber so ein bisschen in der Lernphase. Aktuell haben wir viele Stellen, gerade wenn wir größere Datenmengen abrufen, anlegen. Das dann weiß ich nicht. Wir wollen jetzt für den Test 100 Teams haben. Dann läuft es gerade darauf hinaus, dass jedes Team einzeln angelegt wird statt in einem Batch alle 100 zusammen. Und dass es dann rein von der Vorbereitung des Tests ist. Dass es dann schon relativ langsam ist, werden wir auch mit Sicherheit umstellen. In der Anfangsphase hatten wir es tatsächlich mal so, dass wirklich alle Tests da komplett unabhängig voneinander waren. Also für jeden Test wurde ein Postgres gestartet und ein CIC log, und das haben wir dann irgendwann mal so umgestellt, dass das halt, wenn die Tests laufen, alles genau einmal passiert und dann für alle Tests das gleiche verwendet wird, die aber mit verschiedenen Daten arbeiten. Also jeder Test hat einen anderen Kunden, den er praktisch verwendet, sowohl bei anderen RAM als auch bei uns in der Form Vorgangs Management in der Datenbank. Es ist auch was anderes. Und seit dem sind die halt auch ein ganzes Stück schneller geworden. Aber das, was wirklich die meiste Zeit frisst, ist das Anlegen der Testdaten, und zum Teil auch das Überprüfen. Also ich habe jetzt zum Beispiel gerade zum Thema Löschen einen Test geschrieben. Also das betrifft jetzt wirklich nur DAO, wo ich jetzt sage, okay, ich will gerne noch mal überprüfen, dass wenn ich den einen Kunden lösche, dass sich bei anderen Kunden, die auch da sind, nichts ändert.
Sven
00:50:31
Guter, guter Test.
Benjamin
00:50:32
Ja, und in den Testdaten werden halt wirklich zufällig mehrere Kunden angelegt. Zehn Stück hatte ich glaube ich genommen mit verschiedenen Teams, mit vielen Usern, das heißt alles zufällig generiert und dann. Was ich mache ist, dass ich einmal am Anfang, bevor ich das Löschen mache, zähle ich alle Tabellen durch und zwar für jeden Kunden einzeln, um nachher sagen zu können, für diesen Kunden waren so und so viele Nutzer in der Datenbank, für diesen so und so viele usw. Dann wird halt das Löschen aufgerufen und danach zähle ich noch mal alles durch, um halt dann vergleichen zu können, okay, bei dem Kunden, den ich löschen wollte, da ist jetzt wirklich nichts mehr da. Bei allen anderen ist es unverändert und allein dieses Zählen dauert erschreckend lange.
Sven
00:51:09
Aber die anderen sind gleich geblieben. Das ist natürlich ein klassischer Testfall, wo manuelle Testfahrten auch wieder interessant wären, weil da natürlich gleich ein Use Case interessant ist, dass dann noch irgendein User beim anderen Kunden haargenau so heißt oder die gleiche ID hat oder wie auch immer. Gleichzeitig wird sich aber der gleiche primäre Merkmale irgendwie.
Benjamin
00:51:36
Ja, prinzipiell ja. Praktisch hat das für mich bei dem Test nicht so die Relevanz, weil wir unser Datenmodell so angelegt haben, dass alle Tabellen, die die hat, irgendwie kundenspezifisch sind. Da haben wir ja unsere eigenen Tabelle und dann haben wir haben die anderen Tabellen, haben alle von uns die Beziehung dahin und das ist immer mit Calling Glied eingerichtet. Und der große Vorteil ist halt, dass ich beim Delete ich lösche wirklich nur den Eintrag in der Tabelle. Alles andere passiert automatisch und da vertraue ich dann halt schon auch ein Stück weit der Datenbank, dass sie das richtig macht.
Sven
00:52:13
Und natürlich unseren Queries und der Art, wie wir die Anfragen machen.
Benjamin
00:52:17
Ja, Ja, ja.
Sven
00:52:17
Dass wir die richtig machen, dass es nicht zu einer Löschung an einer anderen Stelle führt.
Benjamin
00:52:20
Naja, die Löschung kann eigentlich nicht an anderer Stelle passieren, weil ich wie gesagt, ich lösche ja nur den Eintrag in der Tabelle. Alles andere passiert ja automatisch. Die anderen Tabellen fasse ich manuell überhaupt nicht an. Das macht nur Postgres. Aber da ich halt nicht quasi jetzt noch in der Usertabelle irgendwas lösche, wo ich irgendwelche Bedingungen habe, wo ich halt sage okay.
Sven
00:52:41
Okay.
Benjamin
00:52:41
Da können nicht. Wenn jetzt der Nutzer bei dem Kunden gleich heißt, könnte es Probleme geben. Situation habe ich nicht und damit halte ich es auch jetzt nicht unbedingt für nötig, das unbedingt zu testen. Aber ansonsten hättest du recht. Also manuelle Testdaten hätte da natürlich den großen Vorteil, dass ich wüsste, wie viel nachher übrig sein müsste. Ich müsste nicht so viel zählen in der Datenbank, aber gut.
Sven
00:53:08
Es ist ja auch ein zweischneidiges Schwert. Also es ist natürlich super cool, die ganze Sicherheit zu haben und ich glaube, das ist heutzutage eigentlich auch fast unstrittig. Aber natürlich bin ich schon manchmal in der Situation, dass irgendjemand kommt. Ach Mensch Sven, ich war da gerade auf einer Messe gewesen und da ist ein anderer Anbieter und der hat nur fünf Entwickler. Und wer macht den dreifachen Umsatz von uns? Und der Gründer hat ja auch selber mitentwickelt und die kriegen es auch hin. Und manchmal fragt man sich auch warum dauert das bei uns so lange? Und? Was würdest du dazu sagen? Weil ich glaube, einer der großen Unterschiede wird sicherlich sein. Zum Beispiel das Thema Testabdeckung. Und was ich bei euch auch schon häufiger gehört habe oder was ich auch selber kenne, ist, da hat man dann mal eine Änderung, die man vornehmen will, gerade in so einer frühen Phase des Produkts oder Projekts, wo alles noch so ein bisschen im Fluss ist. Und dann sagt man ja die Änderung, die hätte eigentlich in zehn Minuten erledigt. Aber die Tests habe ich bestimmt einen halben Tag, einen Tag mit beschäftigt, bis ich das dann zurechtgebogen habe, dass das wieder funktioniert. Was sind so deiner Meinung dazu?
Benjamin
00:54:18
Also die die Erfahrung so extreme hatte ich noch nicht. Es ist schon tendenziell so, dass ich auch sagen würde also ich habe so das Gefühl, Produktiv Kotest Code, das ist nicht so Hype Hype, sondern eher so 1/3, 2/3 vielleicht. Also keine Ahnung, ist jetzt einfach nur ein großes Gefühl. Allerdings. Also es ist schon ein zweischneidiges Schwert. Es kostet auf jeden Fall Zeit. Da darf man sich keine Illusionen machen. Ich kann halt jetzt schon sagen, gerade am Anfang, wo man, wo auch so viel noch nicht fest steht und so viel im Fluss ist, sind Tests auch wieder sehr wertvoll. Denn was ich jetzt noch gar nicht hatte, war die Situation, dass ich praktisch sagen konnte okay, ich habe jetzt, ich will jetzt hier was umbauen. Und die Tests, die es bisher gab, die sind, die kann ich dann auch alle neu schreiben, die sind wertlos, weil ich halt einfach alles so massiv umstelle, alles so massiv anders wird, dass die bestehenden Tests gar nicht mehr bringen. Es ist schon oft so, gerade bei diesen Integrationtests auf Controler Ebene, da da dann halt auch ein Request auf irgendeinen Endpoint kommt. Solange die API stabil ist, also solange wir nicht URLs anpassen und zwar im größeren Umfang anpassen, liefern die mir immer noch ein Ergebnis, was mir sagt okay. Zumindest der Happy Pastewka getestet ist. Der funktioniert immer noch. Der sieht von außen immer noch gleich aus. Und ansonsten hast du im Zweifelsfall oft auch Situationen, dass du irgendwas umbaus und dann anhand der Tests erkennst. Ah, okay, okay, in Tests wird noch irgendein Spezialfall behandelt. Den habe ich jetzt aber so gar nicht mehr. Also der Test funktioniert. Also selbst wenn ich ihn jetzt so weit anpasse, dass es wieder zu den Änderungen passt, die ich gemacht habe, dann habe ich hier einen Spezialfall getestet, den es gar nicht mehr gibt. Dann habe ich halt sofort auch noch mal den Rahmen da. Stimmt das, dass der keinen Sinn mehr gibt oder bräuchte ich ihn eigentlich immer noch? Also fehlt mir jetzt irgendwas? Habe ich was unterschlagen oder gegebenenfalls war das ja auch der Grund für den Umbau, den ich gemacht hatte, es da irgendwo ganz viele Spezialfälle drin waren, die ganz komisch waren. Dann kann ich sagen, den kann ich jetzt löschen, den Test brauche ich nicht mehr. Ist dann auch eine schöne Sache. Ich Ich weiß nicht, ob man so so ohne Weiteres klar sagen kann, es bringt in Summe was oder es bringt nichts. Ich denke schon. Es gibt ganz viele Umbauten, die würde ich mich ohne Tests nicht trauen. Da würde ich sagen Ja, ich habe keine Ahnung, was ich danach manuell alles testen muss, damit ich weiß, es funktioniert noch alles so, wie es ist. Da verlasse ich mich an vielen Stellen dann schon einfach auf die Tests und mache danach nur noch irgendwie so einen Smoke Test und da bringt es dann schon auch definitiv was.
Sven
00:56:57
Also bei mir ist es auch so Wenn ich über die Produktlebenszeit gucke, also die den gesamten Zyklus eines Produkts, dann bin ich zu 100 % davon überzeugt, dass es bombastisch viel Zeit spart, weil was man alles manuell testen müsste, wenn er diese Sachen nicht hätte und wie unsicher es wäre, Refactorings durchzuführen oder technische Umbauten, die einfach notwendig sind. Das könnte man alles überhaupt nicht tun, wenn man diese Tests nicht hat. Wenn man natürlich so diesen MVP Minimal variable Produktpad vor Augen hat, fragt man sich manchmal auch Boah, vielleicht sollten wir doch erst mal zusammen, dass man ein Produkt haben und dann anfangen, die Tests einzuziehen. Dann hat sich auch alles ein bisschen gesattelt und alles ist zurechtgerückt. Auf der anderen Seite ist natürlich gleich das Problem, Ja, dann habe ich die Software auch nicht entwickelt und weiß gar nicht, ob ich hinterher noch die Testschreiben kann. Und auf der anderen Seite wird natürlich auch kein Unternehmen hingehen und sagen Ja, super, jetzt haben wir nach einem Jahr Entwicklungszeit den P rausgehauen, dann setzen wir uns jetzt mal ein Jahr hin und schreiben die Tests. Und wahrscheinlich wird es dann sogar ein Jahr dauern, wenn er die gleiche Abdeckung haben wollen würde. Also von daher stellt sich für mich für ein qualitativ hochwertiges Produkt, was dann auch lange im Markt ist und viele Kunden haben soll. Stellt sich die Frage einfach in 2023 nicht mehr? Sind Tests sinnvoll? Oder sind sie nicht? Was ich auch ganz spannend finde, ist die Frage Gibt es irgendwo ein Mittelweg, wo man vielleicht sagen kann, gibt es irgendwelche Sachen, die besonders viel, Aufwand in der Erstellung und in der Pflege erzeugen. Die natürlich auch nützlich sind? Aber wo man zum Beispiel sagen könnte, wenn man das weglassen würde, dann könnte man es ein bisschen beschleunigen und hätte nur ein bisschen Sicherheit eingebüßt, quasi.
Benjamin
00:58:40
Genau das ist für mich. Sind für mich diese Zufalls generierten Testdaten etwas, was sehr, sehr viel Performance bringt? Also bei der Testentwicklung dann, wie du schon sagtest, dieses Testdaten schreiben. Das ist enorm aufwendig. Da macht man sich dann auch oft wahnsinnig viele Gedanken.
Sven
00:58:52
Furchtbar. Ja.
Benjamin
00:58:55
Auch viel mehr als notwendig wären. Ja, dann fängt man plötzlich darüber an, darüber nachzudenken, wie geht es einem Teammitglieder hin zu. Oh, jetzt habe ich acht Männer und zwei Frauen. Wie sieht denn das aus? Was sagt das über mich aus? Also es ist jetzt ein relativ billiges Beispiel, aber.
Sven
00:59:12
Ja, finde ich gut.
Benjamin
00:59:13
Auch auch an ganz anderen Stellen, denn dann fängt man dann an, Zeit damit zu verschwenden, dass man Teams anlegt und dabei Teamnamen wählt, die irgendwie sinnvoll sind, obwohl das für den Test völlig egal ist. Es spielt keine Rolle.
Sven
00:59:24
Vollkomiker. Ich. Ich kenne das. Was für Zwängen man da unterliegt, wenn man sich einfach nur Testdaten ausdenken soll. Das ist schockierend. Aber.
Benjamin
00:59:32
Und so wie wir es jetzt haben, auch mit dem Framework sage ich halt okay, ich brauch jetzt für diesen Test 20 Teams, legt mir die mal an, Punkt, und dann sind sie da und das geht dann halt alles relativ fix. Auch da muss man sagen, da hatten wir durchaus eine gewisse Lernkurve. Und ich habe auch jetzt bei der Vorbereitung auf diese Episode wieder so ein paar Sachen gelernt, wo ich dachte ah, okay, das hätten wir uns einfacher machen können, wenn ich das gewusst hätte. Und es gibt da noch so ein paar Sachen, die wir anpassen wollen. Aber so im Großen und Ganzen ist es halt so, dass wir da inzwischen Framework haben, was einfach ganz gut funktioniert und was uns da auch echt Zeit bringt. Also dann Testdaten in der letzten Firma. Ich glaube, wir hatten am Ende zwei oder drei verschiedene DSL zum Test Daten anzulegen, weil wir immer mit irgendwas angefangen haben und dann irgendwann feststellen ach Mist, das greift jetzt hier nicht mehr. Wir bräuchten jetzt hier eigentlich irgendwas anderes und.
Sven
01:00:24
Stimmt. Dann verbringst du Zeit damit DSL zu schreiben, denn das die den Code wollen, weil du mußt die Testdaten ja irgendwo rumzuliegen haben, dann versuchst du die bestehenden Testdaten so zu erweitern, dass sie für möglichst möglichst viele User, also für möglichst viele Testfälle, gültig sind. Womit du denn bei einem Testfall Testdaten hast, die vollkommen okay sind. Also sind alles bekannte Probleme, die dadurch adressiert werden. Das wäre wirklich sehr spannend.
Benjamin
01:00:49
Ja genau. Und wie gesagt, es hat uns enorm beschleunigt, das zu machen. Ansonsten ja, man, man muss sich da einfach auch mal selber bremsen und dann irgendwann überlegen, was was lohnt sich jetzt hier wirklich noch abzudecken. Ja, aber auch da ist es so, dass dieses Arbeiten mit also nicht nur das Arbeiten mit automatisch generierten Testdaten, sondern auch solche Blöcke, wo ich halt ein und denselben Test mit verschiedenen Daten ausführe. Das macht es auch zum Teil sehr, sehr einfach, halt ganz, ganz viele Konstellationen ab zu testen mit sehr wenig Aufwand. Ja, also nehmen wir mal an, jetzt mal ganz, ganz primitiv gedacht. Ich habe mir irgendwie meinen HTTP Client geschrieben und will jetzt am Ende gucken, dass da irgendwie der, der den aufruft, mit allen Fehlerquellen, die auftreten können, umgehen kann. Ja, dann gibt es irgendwo in irgendeiner Bibliothek bestimmt mal alle möglichen HTTPstatuscodes, also alle offiziellen, also alle Standardcodes als Namen kann ich mir mal alle Werte holen, daraus die Erfolgswerte rausfiltern und dann halt sagen, Ich hoffe jetzt diese Testfunktion mit denen auf und kann so testen, dass egal was da für einen Statuscode kommt, man nicht irgendwie eine Explosion wirft, sondern immer das macht, was sie erwarten würde. Ja, und das macht schon vieles sehr viel einfacher und damit auch sehr viel schneller.
Sven
01:02:12
Wobei man da natürlich aufpassen muss. Klar ist einfach dann möglichst viele Varianten durchzutesten. Aber über die Zeit hinweg wird es natürlich auch die Tests machen. Auch wenn man jetzt eine Schleife mit 100 Statuscodes, die wird jetzt irgendwie.
Benjamin
01:02:22
Da kommt.
Sven
01:02:25
Für ein Unit Test nicht ewig dauern, aber.
Benjamin
01:02:27
Ja. Ich wollte gerade sagen, es kommt drauf an, wo man das macht. Also bei Integration Tests muss man auf jeden Fall vorsichtig sein.
Sven
01:02:31
Da tut es richtig weh.
Benjamin
01:02:34
Da kann es schon in der Performance einen relevanten Unterschied machen, ob ich sage, ich arbeite jetzt hier mit zehn Teams oder ich arbeite mit 100. Meine bisherigen Erfahrungen aus den Unittests ist das jetzt praktisch keine Rolle. Also da kannst du auch mal sagen ach was soll's, ich habe 1000 Teams und arbeite mit denen. Das geht immer noch ratzfatz.
Sven
01:02:54
Na gut, dann ist es definitiv Zeit für.
Benjamin
01:03:12
Es ist nicht wirklich die Erkenntnis der Woche, hat aber mit der Episode zu tun in dieser Woche. Unser Offside war einfach zu wenig, als dass ich da eine besondere Erkenntnis hätte treffen können.
Sven
01:03:23
Du darfst auch die Wochen bis zur letzten Episode nehmen.
Benjamin
01:03:26
Nee, es geht generell auch noch um diese automatisch generierten Testdaten. Prinzipiell bin ich davon überzeugt, ist super. Man muss allerdings auch immer damit rechnen, dass man damit total auf die Nase fällt und ganz komische Sachen passieren und nicht reproduzierbare Sachen. Eine wichtige Sache ist bei Sachen, die eindeutig in der Datenbank sein müssen, darauf zu achten, dass die Feldlänge lang genug gewählt wird, Nicht Also als Beispiel bei uns. Der Teamke kann von theoretisch von 1 bis 8 Zeichen lang sein. Wenn ich das jetzt generieren lasse und dabei genau dieses Peter nehme 1 bis 8 Zeichen und ich lasse mir dann 100 Teams generieren, dann ist leider die Wahrscheinlichkeit schon relativ hoch, dass ich einen Konflikt kriege, weil er mir halt zweimal ein Team mit Namen mit CIA generiert oder ähnliches. Ja, also da gab es ein paarmal Situationen auch gerade. Abhängig davon, was für einem sieht man dann arbeitet. Wo wir wirklich davor saßen und dachten verdammte Scheiße, warum läuft der Test bei mir localhost durch und auf dem Server nicht aufgeht? Oder warum läuft er durch, wenn ich ihn einzeln ausführe, aber nicht, wenn ich alle zusammen ausführe und umgekehrt. Und irgendwann, das war halt so bei den Teamcis, das war auch bei den Usern so, dass wir dann irgendwann angefangen haben, so die Mindestlänge für die generierten Daten immer größer zu wählen. Also wenn man es einmal verstanden hat, dann weiß man irgendwann auch, worauf man achten muss. Aber am Anfang saßen wir davor und haben wie immer so schön geguckt wie das Schwein ins uhrwerk, weil es halt echt überhaupt nicht verständlich war. Warum, Warum? Wie kommt das aber?
Sven
01:05:02
Und nichts hasst man mehr als Entwickler, wenn dieser Kram das hier eigentlich durchläuft. Aber lokal, das ist dann wieder so, diese Willkürlichkeit ist jetzt in der Umgebung irgendwas anders. Ja, spannend.
Benjamin
01:05:12
Ja, ja. Also im Ganzen war es auch für uns erst mal völlig willkürlich, aber irgendwann dann mal verstanden. Achso, okay. Und ich glaube, ich habe auch in zwei Schritten, da die Mindestlängen inzwischen ein ganzes Stück angehoben. Der Benutzername muss jetzt, glaube ich, mindestens zehn Zeichen lang sein, dann ist man schon auf der sicheren Seite. Aber auf die Idee muss man halt auch erst mal kommen.
Sven
01:05:36
Hmmm. Und gibt es da irgendwie die Möglichkeit, dem Generator zu sagen, dass es keine doppelten Werte generieren?
Benjamin
01:05:44
Interessante Frage, habe ich noch gar nicht geguckt, aber ich glaube erst mal nicht bzw. Was man schon machen kann. Da müsste man dann halt aber auch selber eingreifen, dass ich praktisch sage, ich hol mir erstmal eine Liste, die viel, viel größer ist als das, was ich brauche und hol mir dann die raus, die ich haben will. Also die, also dass ich dann selber über Filter dafür sorge, dass keine Doppelten drin sind und Ähnliches. Für uns war es in dem Fall einfacher zu sagen, wir erhöhen einfach die Mindestlänge, um auf die Art und Weise in eine sichere Situation zu geraten. Es ist eine spannende Frage. Ich muss mal nachgucken, ob das nicht vielleicht sogar noch einfacher wäre.
Sven
01:06:23
Gut. Ja. Dann haben wir es geschafft. Dieses Mal ein bisschen über der Zeit. Aber ist ja auch ein spannendes Thema. Und dann werden wir sicherlich noch mal eine Episode machen zum Thema Frontend Testing. Ansonsten Feedback auf der Website. Oder ein schöner Satz schon. Tschüss.

Feedback

Wir freuen uns über Dein Feedback – sowohl zu unseren technischen Erlebnissen und Entscheidungen als auch zu unserem Podcast. Gibt es vielleicht ein Thema, dass Du gerne behandelt haben möchtest? Dann kontaktiere uns hier gerne.

Mit einem Klick auf "Nachricht absenden" erklärst Du Dich damit einverstanden, dass wir Deine Daten zum Zwecke der Beantwortung Deiner Anfrage verarbeiten dürfen. Die Verarbeitung und der Versand Deiner Anfrage an uns erfolgt über den Server unseres Podcast-Hosters LetsCast.fm. Eine Weitergabe an Dritte findet nicht statt. Hier kannst Du die Datenschutzerklärung & Widerrufshinweise einsehen.

★★★★★

Gefällt Dir die Show?
Bewerte sie jetzt auf Apple Podcasts