WEBVTT

00:06.090 --> 00:10.290
Das Gleiche gilt natürlich auch für Industrie, für Geschäftssoftware.

00:10.610 --> 00:16.550
Wenn man Software für ein Automobil produziert, programmiert, selber

00:16.550 --> 00:19.510
testet, herausfindet, da ist ein Fehler drin, den Fehler behebt, dann

00:19.510 --> 00:20.290
ist alles in Ordnung.

00:20.870 --> 00:23.430
Was nicht funktioniert ist, wenn man das Ding rausgibt, das läuft im

00:23.430 --> 00:26.490
Auto, das ist ein paar Millionen Mal verbaut, die Autos fahren in der

00:26.490 --> 00:28.790
ganzen Weltgeschichte rum und jetzt passiert irgendwas.

00:29.730 --> 00:31.810
In dem Augenblick haben Sie ein Problem, wenn Sie die Software

00:31.810 --> 00:32.530
geschrieben haben.

00:33.710 --> 00:36.310
Also, grundsätzlich lassen sich Fehler nicht vermeiden, wir sind alle

00:36.310 --> 00:36.750
menschlich.

00:37.610 --> 00:39.050
Es geht einfach nicht.

00:39.350 --> 00:41.550
Software ist viel zu komplex, um sie einfach auf Anhieb mal so

00:41.550 --> 00:42.590
fehlerfrei hinzuschreiben.

00:43.090 --> 00:47.350
Aber, was Sie machen können ist, dafür sorgen, dass wenn es schief

00:47.350 --> 00:50.650
geht und wenn sich etwas fehlverhält, dass Sie das sofort merken,

00:50.870 --> 00:54.090
indem Sie selbst provozieren, dass dieser Fehler auftritt.

00:54.290 --> 00:56.870
Und genau das ist Testen.

00:59.430 --> 01:07.630
Einer der ersten Fehler, hier, einer der ersten Software-Bugs, ist das

01:07.630 --> 01:11.910
englische Wort für Softwarefehler, die jemals aufgetreten sind, ist in

01:11.910 --> 01:17.090
einem Großrechner aufgetreten, in 1943 war das, glaube ich.

01:17.590 --> 01:20.070
Das sind riesengroße Schränke und irgendwann hat das nicht mehr

01:20.070 --> 01:21.290
funktioniert, was sie da gemacht haben.

01:21.750 --> 01:23.890
Das hat sehr lange gebraucht, bis sie herausgefunden haben, was genau

01:23.890 --> 01:24.310
los ist.

01:24.310 --> 01:27.010
Und dann haben sie diese Motte gefunden, die sich in eines der Relays

01:27.010 --> 01:31.450
draufgesetzt hat quasi und das Ding zum Versagen gebracht haben.

01:31.550 --> 01:35.650
Deswegen, das ist sozusagen der erste Software-Bug, den es so gab.

01:36.630 --> 01:39.450
Ist allerdings nicht der Ursprung von dem Begriff Bug, also das gab es

01:39.450 --> 01:41.150
schon vorher tatsächlich.

01:42.890 --> 01:45.610
Andere Softwarefehler, vielleicht ein bisschen realere Softwarefehler,

01:46.150 --> 01:50.550
sind zum Beispiel der Terac 25 Bestrahlungsgerät, in dem ein

01:50.550 --> 01:53.930
Softwarefehler dafür gesorgt hat, dass das Gerät Menschen verstrahlt

01:53.930 --> 01:54.090
hat.

01:55.010 --> 01:57.870
Einige Menschen gestorben, das ging über Jahre hinweg, bis man gemerkt

01:57.870 --> 01:59.770
hat, was da nicht richtig läuft.

02:00.210 --> 02:03.870
Das Gerät hat die Benutzereingabe nicht korrekt verarbeitet.

02:03.950 --> 02:07.770
Wenn der Benutzer geübt war und das ganz schnell eingeben konnte, dann

02:07.770 --> 02:11.950
hat sich das Gerät im Prinzip an dieser Eingabe verschluckt und hat

02:11.950 --> 02:15.410
dann eine sehr, sehr hohe Strahlenbelastung erzeugt, also einen

02:15.410 --> 02:18.350
wesentlich höheren Strahl abgeschickt auf den Patienten, als das

02:18.350 --> 02:19.230
eigentlich gedacht war.

02:20.030 --> 02:22.670
Das ist erst passiert, wenn der Benutzer sehr schnell eingegeben hat,

02:22.750 --> 02:27.450
also durch die Eingabemaske gesprungen ist und den Befehl abgeschickt

02:27.450 --> 02:27.670
hat.

02:27.790 --> 02:29.850
Das ist nicht passiert, wenn man das langsam eingibt.

02:30.810 --> 02:33.650
Und genau deshalb ist der Fehler erst sehr spät aufgetreten überhaupt.

02:33.870 --> 02:35.710
Und deswegen hat man lange überhaupt gar nicht gemerkt, dass dieser

02:35.710 --> 02:36.490
Fehler existiert.

02:37.090 --> 02:40.130
Als das System entwickelt wurde, hat niemand die Übung gehabt, so

02:40.130 --> 02:41.130
schnell eingeben zu können.

02:41.130 --> 02:44.810
Das heißt, alle haben sehr langsam, Feld für Feld, die Eingabemaske

02:44.810 --> 02:47.390
ausgefüllt, abgeschickt und das war alles in Ordnung und das ging ein

02:47.390 --> 02:48.570
paar Jahre ganz gut eigentlich.

02:49.030 --> 02:51.570
Und irgendwann waren die Leute, die das Ding bedient haben, so schnell

02:51.570 --> 02:54.150
in der Eingabe, dass sie plötzlich diesen Fehler provoziert haben.

02:54.770 --> 02:58.750
Und dadurch, dass das System dermaßen fehlerhaft war und eigentlich

02:58.750 --> 03:01.910
die ganze Zeit sich mit irgendwelchen Fehlermeldungen beschwert haben,

03:02.470 --> 03:05.310
waren die Benutzer davon dann auch noch darauf trainiert, sämtliche

03:05.310 --> 03:06.670
Fehlermeldungen einfach zu ignorieren.

03:06.770 --> 03:09.190
Das beschwert sich sowieso, dann starte ich neu und mache weiter.

03:10.490 --> 03:12.890
Und wie gesagt, das hat eben Menschenleben gekostet.

03:14.210 --> 03:16.150
Toyota war in den Nachrichten zum Beispiel.

03:18.010 --> 03:21.810
Da hieß es zuerst, ja das Gaspedal, dann hieß es, ja das sind

03:21.810 --> 03:24.210
Fußmatten, wir tauschen die Fußmatten aus.

03:25.210 --> 03:27.270
Dann gab es eine Untersuchung in der Zwischenzeit, da haben sich die

03:27.270 --> 03:28.650
NASA den Code angeguckt.

03:29.130 --> 03:31.130
Dann haben sie gesagt, ja der Code ist schon in Ordnung eigentlich.

03:31.230 --> 03:33.410
Jetzt gab es eine zweite Untersuchung und da hieß es dann, ne der Code

03:33.410 --> 03:34.750
ist eigentlich nicht in Ordnung.

03:34.750 --> 03:37.950
Und diese Fehler, die da aufgetreten sind, die können und sind

03:37.950 --> 03:40.550
wahrscheinlich auch durch Softwarefehler ausgelöst worden.

03:40.630 --> 03:43.570
Die Software war einfach unglaublich schlampig geschrieben, die war

03:43.570 --> 03:44.590
voller Fehler.

03:44.890 --> 03:47.510
Da wurden einige Fehler mehr gefunden als das, was jetzt tatsächlich

03:47.510 --> 03:48.810
zu Problemen geführt hat.

03:50.290 --> 03:52.670
Da wurde auch nicht ausreichend getestet an der Stelle.

03:53.170 --> 03:56.810
Andere Beispiele für Sicherheit im Sinne von Einbruchssicherheit sind

03:56.810 --> 04:00.710
dann Hackerangriffe auf diverse amerikanische Firmen, auf Google

04:00.710 --> 04:03.630
Server zum Beispiel von chinesischen Hackern aus.

04:04.350 --> 04:09.150
Oder im Jahr 2003 ein Stromausfall in Nordamerika, der das komplette

04:09.150 --> 04:13.450
Stromnetz in einem großen Bereich für zwei Tage komplett lahmgelegt

04:13.450 --> 04:13.770
hat.

04:14.330 --> 04:17.050
Kein Strom mehr, Wasserversorgung ist in manchen Städten

04:17.050 --> 04:21.610
zusammengebrochen, die Kommunikation ist zusammengebrochen, die

04:21.610 --> 04:24.650
Krankenhäuser konnten auf Notversorgung umstalten, aber viele andere

04:24.650 --> 04:25.210
Sachen nicht.

04:25.750 --> 04:28.290
Manchmal ist die Notversorgung bei der Belastung auch kaputt gegangen.

04:30.750 --> 04:32.790
Das sind alle Softwarefehler und die sollten eigentlich nicht

04:32.790 --> 04:34.410
passieren, die dürfen eigentlich nicht passieren.

04:36.610 --> 04:37.710
Was lernen wir daraus?

04:38.710 --> 04:41.630
Erstmal müssen wir natürlich alle Fehlersituationen behandeln, die

04:41.630 --> 04:42.710
irgendwie auftreten können.

04:42.810 --> 04:46.650
Alles bedenken, was kann passieren, was kann Unerwartetes passieren.

04:48.730 --> 04:52.190
Alles, was der Benutzer irgendwie eingibt, muss nochmal kontrolliert

04:52.190 --> 04:52.470
werden.

04:52.550 --> 04:53.290
Ist das in Ordnung?

04:53.390 --> 04:54.390
Kann das wirklich so sein?

04:54.450 --> 04:55.790
Hat der Benutzer einen Fehler gemacht?

04:57.650 --> 05:04.770
Alle Fehler behandeln und dann testen, ausgiebig testen, richtig

05:04.770 --> 05:05.790
ausgiebig testen.

05:08.070 --> 05:11.270
Und das ist super anstrengend und das ist super schwierig, das korrekt

05:11.270 --> 05:11.610
zu machen.

05:12.570 --> 05:15.310
Und es ist einfach eine Arbeit, die sehr, sehr ermüdend ist.

05:15.930 --> 05:18.790
Es macht nicht wahnsinnig viel Spaß, muss man ganz ehrlich sein.

05:19.050 --> 05:19.930
Wer testet gerne?

05:20.330 --> 05:22.790
Man hat gerade das Ding zu Ende, die Übungsaufgabe ist fertig, man

05:22.790 --> 05:26.290
lädt das hoch und sagt sich, ach komm, das passt schon, ich habe jetzt

05:26.290 --> 05:30.130
keine Lust mehr, ich gehe jetzt lieber, keine Ahnung, auf Party oder

05:30.130 --> 05:30.790
sonst irgendwas.

05:31.030 --> 05:34.250
Aber genau an der Stelle fangen wir dann an zu testen und wenn wir die

05:34.250 --> 05:35.910
Fehler finden, dann ziehen wir Ihnen Punkte ab.

05:36.230 --> 05:38.690
Wenn Sie die Fehler finden, dann können Sie die Fehler nochmal

05:38.690 --> 05:39.130
beheben.

05:39.590 --> 05:41.410
Also, ja, testen Sie.

05:41.790 --> 05:44.530
Das ist so, quasi wenn Sie jetzt aufstehen müssten und gehen müssten

05:44.530 --> 05:47.430
und den Rest der Vorlesung nicht mehr zuhören könnten, das ist die

05:47.430 --> 05:50.990
eine Message, die Sie mitnehmen müssen, testen Sie noch gründlicher

05:50.990 --> 05:53.850
und noch ausgiebiger, als Sie programmiert haben an erster Stelle.

05:56.930 --> 05:59.290
Aber wann ist ein Programm überhaupt fehlerhaft?

06:00.450 --> 06:06.850
Fehlerhaft bei Übungsaufgaben heißt, wenn die Aufgabe verfehlt ist,

06:07.010 --> 06:09.950
wenn das Programm nicht das tut, was in der Übungsaufgabe drin steht.

06:11.150 --> 06:15.410
Insofern könnte man sagen, also erstmal würde man sagen, die Software

06:15.410 --> 06:16.650
tut nicht das, was sie soll.

06:16.650 --> 06:20.090
Wir sagen Ihnen, was die Software tun soll, Sie setzen das um.

06:21.930 --> 06:24.870
Aber im Allgemeinen ist soll sehr vage.

06:25.070 --> 06:28.070
Deswegen schreiben wir das quasi als Übungsaufgabe auf und in der

06:28.070 --> 06:32.050
Praxis ist das normalerweise dann als Spezifikation aufgeschrieben.

06:32.210 --> 06:35.690
Das heißt, man stellt Anforderungen an die Software, man schreibt die

06:35.690 --> 06:38.530
schriftlich auf, man formuliert das alles aus, man beschreibt die

06:38.530 --> 06:40.810
unterschiedlichen Situationen, die erwarteten Ergebnisse.

06:41.330 --> 06:43.670
Ganz ähnlich, wie eine Übungsaufgabe eigentlich gestellt ist.

06:43.670 --> 06:47.250
Noch ausführlicher, noch mehr Beschreibungen von den unterschiedlichen

06:47.250 --> 06:47.750
Verhalten.

06:48.230 --> 06:49.210
Aber im Grunde ist es das.

06:49.850 --> 06:53.970
Und das ist für Sie maßgeblich, was das Programm tun soll.

06:54.310 --> 06:56.790
Und wenn das Programm das nicht tut, dann ist das ein Fehler.

06:58.670 --> 07:01.790
Eine Spezifikation besteht aus einer ganzen Reihe von Anforderungen.

07:02.730 --> 07:05.550
Eine Anforderung ist eine Aussage über eine zu erfüllende Eigenschaft

07:05.550 --> 07:08.110
oder das erbringende Leistung eines Programms, eines Systems.

07:08.110 --> 07:11.870
Das ist im Prinzip das, was der Kunde dann zu Ihnen bringt und sagt,

07:11.970 --> 07:15.030
ich möchte ein System, das das kann und das kann und das kann und das

07:15.030 --> 07:15.750
kann und das kann.

07:15.830 --> 07:18.050
Und dann sind Sie gefordert und sagen, kein Problem, das kann ich

07:18.050 --> 07:18.890
alles programmieren.

07:19.590 --> 07:23.210
Und wann wird der Kunde danach hingehen und sagen, vielen Dank, jetzt

07:23.210 --> 07:26.270
probieren wir mal aus, ob das das kann, was wir da aufgeschrieben

07:26.270 --> 07:27.150
haben, was das kann.

07:27.710 --> 07:29.750
Daran müssen Sie sich messen, die Spezifikation.

07:30.310 --> 07:33.290
Oder in Ihrem Fall jetzt ganz konkret das Übungsblatt oder die

07:33.290 --> 07:34.950
Abschlussaufgabe, die Sie irgendwann machen müssen.

07:36.290 --> 07:38.830
Warum kann Software fehlerhaft sein?

07:39.550 --> 07:43.990
Naja, die eine Möglichkeit ist, dass das Programm abstürzt, Exceptions

07:43.990 --> 07:47.270
geworfen werden zum Beispiel, das wäre in Java quasi ein Absturz.

07:48.050 --> 07:51.930
Oder dass es schlicht und einfach eine Ausgabe produziert, die so

07:51.930 --> 07:52.770
nicht erwartet ist.

07:53.230 --> 07:54.910
Das erste erkennt man relativ schnell.

07:55.030 --> 07:58.810
Eine Exception ist, das werden Sie inzwischen alle gewohnt sein, wenn

07:58.810 --> 08:01.630
eine Exception geschmissen wird, wie sieht das aus in Java, dann wird

08:01.630 --> 08:04.990
der Stack Trace ausgegeben, dann weiß man, oh, das war jetzt nicht so

08:04.990 --> 08:06.230
gut, da ist irgendwas Falsches passiert.

08:06.590 --> 08:08.550
Eine fehlerhafte Ausgabe ist wesentlich subtiler.

08:08.790 --> 08:10.730
Da sieht man nicht sofort, dass die fehlerhaft ist.

08:10.810 --> 08:13.170
Da muss man sich erst überlegen, was war denn eigentlich die korrekte

08:13.170 --> 08:13.770
Ausgabe?

08:14.090 --> 08:16.290
Was wollte ich denn ursprünglich machen an der Stelle?

08:16.690 --> 08:18.390
Ist das jetzt richtig oder ist das nicht richtig?

08:18.490 --> 08:20.890
Und dann kann auch sein, dass sich der Fehler in einer unglaublichen

08:20.890 --> 08:25.030
Menge an Ausgabe versteckt, sodass von 100 Zahlen, die man ausgibt, 99

08:25.030 --> 08:26.650
richtig sind und eine einzige falsch.

08:26.650 --> 08:29.250
Das ist schwierig zu erkennen an der Stelle.

08:29.690 --> 08:32.430
Also Exceptions sind da sehr, sehr dankbar eigentlich, weil sie sofort

08:32.430 --> 08:35.610
sagen, hier ist was passiert, das ist so ein richtig schönes rotes

08:35.610 --> 08:39.030
Blinklicht, das dann angeht, das dann einen anschreit, hier ist ein

08:39.030 --> 08:40.650
Fehler passiert, das hätte nicht sein dürfen.

08:41.650 --> 08:44.110
Es kann auch passieren, es kann auch sein, dass die Software in sich

08:44.110 --> 08:45.170
gar nicht das Problem ist.

08:45.270 --> 08:47.550
Es kann auch schlecht und einfach sein, dass die Anforderungen falsch

08:47.550 --> 08:47.890
sind.

08:49.950 --> 08:52.690
Also zum Beispiel, dass Sie etwas aufgeschrieben haben, das nicht dem

08:52.690 --> 08:54.370
entspricht, was Sie eigentlich haben wollten.

08:54.370 --> 08:57.370
Ist sogar ein sehr häufiges Problem, dass Sie etwas aufgeschrieben

08:57.370 --> 09:01.290
haben, was widersprüchlich ist, wo Sie nicht alles erfüllen können,

09:01.370 --> 09:05.750
was da steht, weil die eine Aussage mit der anderen Aussage, entweder

09:05.750 --> 09:08.230
Sie erfüllen die eine, dann können Sie automatisch die andere nicht

09:08.230 --> 09:10.910
erfüllen, oder andersherum, aber Sie können nicht beide gleichzeitig

09:10.910 --> 09:11.350
erfüllen.

09:13.650 --> 09:16.570
Und das macht das Ganze dann unmöglich zu implementieren.

09:18.210 --> 09:21.790
Es kann auch sein, dass man unterschiedlich über so eine Anforderung

09:21.790 --> 09:25.010
spricht, dass man andere Vorstellungen hat, was die da jetzt aussagt.

09:25.110 --> 09:27.890
Der Kunde schreibt das auf, natürlich, sprachliche Texte haben immer

09:27.890 --> 09:30.430
mehrere Möglichkeiten, sie zu interpretieren und zu verstehen.

09:31.070 --> 09:34.810
Man geht als Programmierer hin, liest das und denkt sich aus seiner

09:34.810 --> 09:37.530
Lebenserfahrung seinen Teil und denkt sich, ah ja, ich weiß, was er da

09:37.530 --> 09:40.970
will, fängt an aufzuschreiben, zu programmieren und hat es zu machen,

09:41.430 --> 09:44.130
gibt das Ding ab und der Kunde sagt, ja das stimmt, so kann man das

09:44.130 --> 09:48.250
auch interpretieren, aber das war jetzt nicht unsere Idee, wir wollten

09:48.250 --> 09:49.830
das eigentlich ganz, ganz anders haben.

09:51.530 --> 09:55.070
Und dann kann es natürlich auch noch sein, dass die Dokumentation

09:55.070 --> 09:55.490
falsch ist.

09:55.610 --> 10:00.890
Man hat das schon irgendwie richtig umgesetzt, man dokumentiert das

10:00.890 --> 10:02.990
falsch, man hat da irgendwie falsch aufgeschrieben, was man

10:02.990 --> 10:03.870
tatsächlich gemacht hat.

10:03.950 --> 10:07.130
Jetzt geht man nochmal hin, jemand anderes benutzt das, glaubt der

10:07.130 --> 10:12.010
Dokumentation, was sie da tut und in Wirklichkeit tut das Programm was

10:12.010 --> 10:13.830
anderes, als diese Dokumentation beschreibt.

10:13.950 --> 10:18.170
Das ist so ein bisschen eine andere Art von Fehler, der da auftreten

10:18.170 --> 10:18.430
kann.

10:19.230 --> 10:22.250
Testen hilft im Allgemeinen, Softwarefehler zu finden.

10:23.290 --> 10:26.410
Und damit ist in erster Linie die erste Art von Fehler gemeint.

10:26.490 --> 10:29.210
Die anderen Arten, ob die Spezifikation korrekt ist oder nicht, das

10:29.210 --> 10:30.510
kann man dem Programm nicht ansehen.

10:31.110 --> 10:33.510
Das muss man auf andere Methoden erarbeiten.

10:34.030 --> 10:37.570
Aber ob das Programm das tut, was in der Spezifikation steht, das kann

10:37.570 --> 10:38.580
man automatisiert testen.

10:42.590 --> 10:44.850
Grundsätzlich gilt, jedes Programm muss getestet werden.

10:46.530 --> 10:48.830
Einmal ausführen, programmieren, einmal ausführen, gucken, ob es

10:48.830 --> 10:49.270
ungefähr tut.

10:49.450 --> 10:53.610
Das ist nicht testen, das ist wesentlich mehr als das.

10:55.370 --> 10:57.510
Im Allgemeinen geht man zweistufig vor.

10:57.630 --> 11:01.070
Ich vermute, wenn Sie mal getestet haben bei Ihren Aufgaben, dann

11:01.070 --> 11:03.670
haben Sie das so ein bisschen intuitiv vielleicht auch schon gemacht.

11:04.450 --> 11:07.270
Das erste ist, Sie überlegen sich Testfälle.

11:08.030 --> 11:10.790
Also welche Fälle sind eigentlich überhaupt interessant, was kann so

11:10.790 --> 11:14.270
passieren, was ist so der einfachste Fall, den man sich vorstellen

11:14.270 --> 11:14.710
kann.

11:17.450 --> 11:20.310
Sie gruppieren das Ganze, Sie klassifizieren das, Sie sagen, ach, das

11:20.310 --> 11:23.870
ist der Fall A und der Fall B und der Fall C, der auftreten kann.

11:26.250 --> 11:29.850
Sie überlegen sich die ganz normalen Fälle, die jeder quasi bedenken

11:29.850 --> 11:30.050
würde.

11:30.170 --> 11:32.070
Sie überlegen sich so ein bisschen Randfälle, was ist so ein bisschen

11:32.070 --> 11:35.570
ein komischer Fall, was könnte im abgefahrensten Fall auch noch

11:35.570 --> 11:36.010
passieren.

11:36.670 --> 11:39.850
Und im zweiten Schritt wählen Sie dann erst konkrete Daten.

11:39.850 --> 11:43.970
Das heißt, Sie überlegen sich, ein Randfall könnte sein, oder eine

11:43.970 --> 11:46.670
negative Zahl, was passiert, wenn ich jetzt eine negative Zahl statt

11:46.670 --> 11:48.030
einer positiven da reinstecke.

11:48.410 --> 11:49.830
Oder ein Standardfall.

11:49.930 --> 11:54.330
Und ein Randfall davon wäre dann vielleicht die Minus 1, als negative

11:54.330 --> 11:56.210
Zahl, die ganz nah an der Null ranliegt.

11:57.930 --> 12:02.550
Und zu jeder der Gruppen an Testdaten wählt man dann, zu jedem Fall

12:02.550 --> 12:08.190
wählt man dann eine ganz konkrete Menge an Eingabedaten, an Zahlen, an

12:08.190 --> 12:09.150
Strings oder was auch immer.

12:10.430 --> 12:13.250
Und macht daraus dann so einen konkreten Testfall.

12:14.430 --> 12:17.130
Idealerweise deckt man alle Situationen ab, die auftreten können.

12:18.410 --> 12:20.630
Insbesondere bei dem ersten Schritt sollte man versuchen, möglichst

12:20.630 --> 12:23.930
vollständig alle Fälle abzudecken, die einem so einfallen können.

12:24.170 --> 12:26.630
Das ist nicht immer möglich, ist meistens nicht möglich tatsächlich

12:26.630 --> 12:27.030
sogar.

12:27.770 --> 12:30.950
Bei der Auswahl der Testdaten muss man sich meistens auf einzelne

12:30.950 --> 12:31.590
beschränken.

12:31.590 --> 12:36.390
Und es ist auch sinnvoll, da nicht zu viele unterschiedliche Testdaten

12:36.390 --> 12:38.890
für eigentlich denselben Testfall zu verwenden, weil man dann

12:38.890 --> 12:41.750
Schwierigkeiten kriegt, seine Tests zu verwalten.

12:43.610 --> 12:44.950
Wir machen einfach mal ein Beispiel.

12:45.790 --> 12:49.090
Wir wollen eine Dreiecke klassifizieren.

12:49.150 --> 12:51.450
Wir haben eine Methode, die nimmt drei Zahlen, das sind die

12:51.450 --> 12:52.630
Seitenlängen der drei Seiten.

12:53.610 --> 12:57.370
Und das Programm soll entscheiden, ist das Dreieck gleichschenklich,

12:57.570 --> 12:59.530
gleichseitig oder ist es weder noch.

13:00.250 --> 13:03.130
Und dann ist die Frage, was sind dafür eigentlich gute Testfälle.

13:05.110 --> 13:06.170
Wir haben eine Menge.

13:07.050 --> 13:08.430
Ein gültiges, weder noch Dreieck.

13:08.510 --> 13:11.690
Klar, ein stinknormales, langweiliges Dreieck, das keine besonderen

13:11.690 --> 13:12.590
Eigenschaften hat.

13:12.850 --> 13:15.190
Sollte man auf jeden Fall einen Fall benutzen.

13:15.630 --> 13:17.950
Ein gültiges, gleichseitiges Dreieck und ein gültiges,

13:18.030 --> 13:19.150
gleichschenkliches Dreieck.

13:19.890 --> 13:23.150
Jetzt haben wir die drei Seiten als Parameter an die Funktion

13:23.150 --> 13:24.950
übergeben, zum Beispiel A, B und C.

13:25.650 --> 13:30.350
Dann sollte man hingehen und einmal A und B, einmal B und C und einmal

13:30.350 --> 13:33.470
A und C gleich machen, weil einfach an der Stelle unterschiedlicher

13:33.470 --> 13:34.470
Code ausgeführt werden.

13:34.930 --> 13:36.570
Die können sich unterschiedlich verhalten.

13:36.650 --> 13:38.790
Es kann sein, dass im einen Fall Fehler sind, im anderen Fall aber

13:38.790 --> 13:39.010
nicht.

13:39.490 --> 13:41.850
Das heißt, man sollte für jede dieser Permutationen einen Fall

13:41.850 --> 13:42.330
einbauen.

13:43.890 --> 13:48.310
Genauso, dass eine Seite zum Beispiel Null ist, dass eine Seite

13:48.310 --> 13:52.250
negative Länge hat, dass zwei Seiten Null sind, dass drei Seiten Null

13:52.250 --> 13:56.630
sind, dass die Summe zweier nicht negative Seiten die dritte Seite

13:56.630 --> 14:00.250
genau ergibt und dass die Summe zweier Seiten kleiner als die dritte

14:00.250 --> 14:02.470
Seite ist, was auch ein Spezialfall ist.

14:02.730 --> 14:04.890
Das kommt man drauf, wenn man sich ein bisschen über diese

14:04.890 --> 14:06.630
Eigenschaften von Dreiecken Gedanken macht.

14:06.730 --> 14:08.370
Das ist alles durchaus machbar.

14:08.830 --> 14:15.310
Als Beispiel mal, wir haben eine Klasse Triangle und die Methode

14:15.310 --> 14:19.370
Classify, die einen Trianglekind zurückgibt, das ist eine Enum mit

14:19.370 --> 14:26.590
Equilateral, Isosceles und Other und die nimmt drei Argumente, A, B

14:26.590 --> 14:30.530
und C und wir wollen sehen, ob diese Klasse, ob diese Methode korrekt

14:30.530 --> 14:30.750
ist.

14:32.030 --> 14:35.590
Dann schreiben wir ein bisschen ausführlichere unsere Spezifikationen

14:35.590 --> 14:36.270
hier in den Kommentar.

14:37.430 --> 14:41.350
Wir haben A, gleichzeitig, wenn alle drei Seiten gleiche Länge haben.

14:41.910 --> 14:45.830
B, gleichschenklich, wenn zwei Seiten gleiche Länge haben, A, ist aber

14:45.830 --> 14:51.070
nicht gleichzeitig ist natürlich und C, alles andere, was diese beiden

14:51.070 --> 14:52.170
Sachen nicht erfüllt.

14:53.230 --> 14:54.150
Das reicht so noch nicht.

14:55.470 --> 14:57.290
Das haut nicht ganz hin, was wir da machen.

14:57.910 --> 15:01.510
Und der Grund dafür ist, dass wir noch einen vierten Rückgabewert

15:01.510 --> 15:01.830
brauchen.

15:01.910 --> 15:05.290
Wir müssen noch die Möglichkeit einbauen, zu kommunizieren, dass es

15:05.290 --> 15:08.170
überhaupt gar kein mögliches Dreieck ist, also Unfug.

15:08.290 --> 15:12.010
Also zum Beispiel eben, wenn eine Seite negative Länge hat, das ist

15:12.010 --> 15:12.770
kein Dreieck mehr.

15:13.250 --> 15:17.270
Oder wenn eine Seite Länge 0 hat, das ist auch ein degenerates

15:17.270 --> 15:17.670
Dreieck.

15:17.830 --> 15:23.590
Oder wenn zum Beispiel die Summe von zwei Seiten kleiner ist als die

15:23.590 --> 15:26.250
dritte Seite, das ist auch kein mögliches Dreieck mehr.

15:27.050 --> 15:30.850
Das müssen wir mit betrachten und das müssen wir nicht nur als

15:30.850 --> 15:35.330
zusätzlichen Punkt D beschreiben, sondern eben auch bei A, B und C

15:35.330 --> 15:38.910
noch zusätzlich mit beschreiben, wann die Fälle eigentlich da nicht

15:38.910 --> 15:39.290
gelten.

15:39.290 --> 15:42.350
Also aus, es sind alle drei Seiten gleich wird, es sind alle drei

15:42.350 --> 15:45.470
Seiten gleich und alle drei Seiten größer als 0.

15:48.910 --> 15:52.710
Und die Spezifikationen, die können wir jetzt als Grundlage nehmen zu

15:52.710 --> 15:53.550
testen.

15:54.050 --> 15:56.570
Also man sieht auch in so einer Spezifikation, selbst für eine relativ

15:56.570 --> 15:59.870
einfache Methode ist es immer nicht ganz einfach, vollständig

15:59.870 --> 16:03.130
hinzukriegen und alle Fälle zu beschreiben, die wichtig sind und genau

16:03.130 --> 16:05.910
zu beschreiben, was in den Fällen passieren soll.

16:06.650 --> 16:08.610
Wir schreiben einfach mal einen kleinen Test.

16:09.510 --> 16:13.690
Triangle-Test, idealerweise bitte die Tests in eine Extra-Klasse

16:13.690 --> 16:15.570
stecken, nicht in dieselbe Klasse einfach dazu packen.

16:16.150 --> 16:18.470
Extra-Klasse, das ist eine andere Funktionalität, das sollte

16:18.470 --> 16:19.350
ausgelagert sein.

16:22.010 --> 16:25.950
Methode Test 1, könnte man besser benennen, sollte man besser

16:25.950 --> 16:29.370
benennen, vielleicht reicht es aber mal für den Zweck hier.

16:30.110 --> 16:34.890
Wir legen die Argumente fest, A, B, C jeweils auf 5.

16:34.890 --> 16:38.630
Wir rufen die Methode auf und wir überprüfen das Ergebnis.

16:39.470 --> 16:42.090
Ist das Ergebnis gleichzeitig?

16:43.390 --> 16:46.610
Was wir noch nicht kennen, ist dieses assert-Schlüsselwort hier,

16:47.350 --> 16:50.030
zumindest kam es bisher in der Vorlesung noch nicht dran, das kommt

16:50.030 --> 16:52.610
später in der Vorlesung noch, für das erste reicht einfach nur, dass

16:52.610 --> 16:55.290
Sie wissen, das überprüft die Eigenschaft und meldet einen Fehler,

16:55.390 --> 16:56.930
wenn die Eigenschaft so nicht gegeben ist.

16:58.530 --> 17:01.410
Relativ einfach, der Test ist sehr kurz gehalten, der soll auch sehr

17:01.410 --> 17:06.790
kurz gehalten sein, je kürzer, desto besser und dann schreiben wir

17:06.790 --> 17:07.830
einen zweiten Test noch dazu.

17:08.270 --> 17:12.970
Der sieht beinahe gleich aus, wir initialisieren wieder, A gleich 3, B

17:12.970 --> 17:16.750
gleich 1, C gleich 3, wir rufen die Funktion auf, genau das gleiche

17:16.750 --> 17:19.930
und auch hier vergleichen wir das Ergebnis wieder mit dem erwarteten

17:19.930 --> 17:20.250
Wert.

17:22.190 --> 17:22.950
Und so geht das weiter.

17:24.690 --> 17:27.530
27 Tests, wie viel auch immer man braucht, um das komplett abzudecken

17:27.530 --> 17:28.710
und alle Fälle bedacht zu haben.

17:28.710 --> 17:32.890
Das ist sehr eintönig, deswegen macht Testen so wenig Spaß.

17:33.610 --> 17:36.310
Man schreibt immer wieder denselben Code hin, es unterscheidet sich

17:36.310 --> 17:39.750
leicht in Variationen, ein bisschen andere Eingabeparameter, ein

17:39.750 --> 17:42.910
anderes Ergebnis, das man erwartet, aber es ist leider notwendig.

17:46.130 --> 17:47.430
Was sind gute Tests?

17:48.550 --> 17:50.550
Sie prüfen genau eine Eigenschaft ab.

17:50.890 --> 17:53.530
Wenn Sie mehr als eine Eigenschaft in einen Test packen und Ihr Test

17:53.530 --> 17:56.730
schlägt viel, dann müssen Sie als allererstes herausfinden, welche der

17:56.730 --> 17:58.350
Eigenschaften eigentlich nicht erfüllt waren.

18:00.350 --> 18:04.450
Wenn die erste Eigenschaft überprüft wird und der Test abbricht, dann

18:04.450 --> 18:06.870
wird die zweite Eigenschaft in dem Test nicht mehr überprüft, dann

18:06.870 --> 18:09.250
sehen Sie gar nicht mehr, ob die überhaupt noch gilt oder nicht.

18:09.950 --> 18:14.790
Das heißt am besten für eine Eigenschaft ein Test, für eine

18:14.790 --> 18:18.590
Eigenschaft möglicherweise auch mehrere Tests, aber pro Test immer nur

18:18.590 --> 18:19.710
eine Eigenschaft prüfen.

18:20.430 --> 18:22.470
Das zweite ist so kurz und prägnant wie möglich.

18:23.170 --> 18:27.470
Wenn Sie lange Tests schreiben, dann ist die Wahrscheinlichkeit, dass

18:27.470 --> 18:29.810
Sie in den Tests Fehler machen, sehr hoch.

18:30.790 --> 18:33.490
Gleichzeitig ist es aber auch so, dass Sie die Tests später nochmal

18:33.490 --> 18:34.090
lesen müssen.

18:34.710 --> 18:37.230
Wenn Sie in dem Augenblick, in dem Sie einen Test schreiben, er

18:37.230 --> 18:39.870
fehlschlägt, dann können Sie relativ schnell identifizieren, was da

18:39.870 --> 18:40.310
schief ging.

18:40.390 --> 18:42.970
Aber wenn Sie Jahre später nochmal auf den Code gucken, weil jetzt

18:42.970 --> 18:46.470
plötzlich der Test fehlschlägt oder jemand anderes den Test

18:46.470 --> 18:50.690
geschrieben hat und der Test geht über mehrere Seiten, dann wissen Sie

18:50.690 --> 18:52.730
in dem Augenblick einfach gar nicht mehr, was der macht.

18:53.150 --> 18:55.310
Also müssen Sie alles nachvollziehen von vorne bis hinten.

18:55.490 --> 18:59.190
Also idealerweise kurze Tests, so kurz wie gerade eben für so eine

18:59.190 --> 19:00.010
einfache Funktion.

19:00.850 --> 19:01.710
Je kürzer, desto besser.

19:02.290 --> 19:04.170
Je kürzer sie sind, desto weniger muss man lesen.

19:05.510 --> 19:08.310
Es sollte immer möglich sein, Tests einzeln auszuführen.

19:08.430 --> 19:10.430
Das ist das gleiche Argument wie gerade eben eigentlich.

19:10.830 --> 19:15.510
Wenn ein Test 1 und ein Test 2 haben und der Test 2 braucht den Test 1

19:15.510 --> 19:19.450
vorher, weil er irgendwie den Zustand des Programms aufbaut, dann

19:19.450 --> 19:22.610
müssen Sie immer Test 1 zuerst ausführen, bevor Sie Test 2 ausführen.

19:22.730 --> 19:25.590
Das braucht mehr Laufzeit, es braucht mehr Verständnis.

19:25.690 --> 19:28.230
Sie müssen Test 1 lesen und verstehen, damit Sie auch Test 2

19:28.230 --> 19:28.670
verstehen.

19:30.050 --> 19:33.090
Und wenn Test 1 fehlschlägt, können Sie Test 2 nicht mehr ausführen

19:33.090 --> 19:33.630
vernünftig.

19:33.890 --> 19:36.070
Das heißt, Sie wissen nicht mehr, ob Test 2 bestanden wird oder nicht.

19:36.390 --> 19:38.850
Das heißt, die Tests sollten immer unabhängig voneinander sein.

19:40.510 --> 19:42.510
Das vierte ist, Sie sollten gut dokumentiert sein.

19:42.610 --> 19:44.930
Sie sollten aufschreiben, was diese Tests überhaupt abtesten.

19:44.930 --> 19:48.330
Sie sollten nicht willkürlich dastehen, sondern ganz klar sagen, ich

19:48.330 --> 19:50.810
prüfe diese Eingabe, ich prüfe diese Ausgabe.

19:51.170 --> 19:54.150
Wenn die Tests so einfach sind wie gerade eben, dann reicht da relativ

19:54.150 --> 19:55.190
wenig Dokumentation.

19:55.270 --> 19:57.530
Aber sobald das ein bisschen mehr wird oder irgendetwas Besonderes

19:57.530 --> 20:00.350
abgetestet wird, ein besonderer Randfall, ist es auf jeden Fall

20:00.350 --> 20:03.270
erwähnenswert zu sagen, welcher Randfall da eigentlich gemeint ist.

20:04.030 --> 20:07.430
Und Sie sollten immer in Bezug zur Spezifikation darstellen.

20:07.530 --> 20:10.350
Sie sollten sagen, ich beziehe mich jetzt auf diesen Satz, in der

20:10.350 --> 20:13.890
Spezifikation steht, die Ausgabe soll so und so aussehen, wenn die

20:13.890 --> 20:16.210
Eingabe so aussieht, das teste ich ab.

20:16.410 --> 20:19.570
Dann weiß man später auch, welche Eigenschaft ist eigentlich in der

20:19.570 --> 20:22.370
Spezifikation jetzt nicht mehr gegeben, wenn der Test fehlschlägt.

20:23.370 --> 20:25.170
Das ist sehr wichtig für die Übersicht später auch.

20:26.930 --> 20:29.930
Idealerweise benutzen Sie existierende Frameworks dafür.

20:30.090 --> 20:31.590
In Java ist das vor allem JUnit.

20:32.370 --> 20:35.170
Das erleichtert einem die Arbeit ungemein.

20:35.350 --> 20:36.950
Es ist integriert in andere Tools.

20:37.170 --> 20:42.970
Sie können das über Server laufen lassen, die jedes Mal, wenn Sie

20:42.970 --> 20:44.470
einchecken, die Tests laufen lassen.

20:44.830 --> 20:47.410
Das hilft Ihnen alles beim Entwickeln ungemein.

20:48.670 --> 20:50.790
Deswegen idealerweise einfach JUnit benutzen.

20:51.250 --> 20:53.590
Es ist auch wirklich am einfachsten, wenn Sie sich daran gewöhnt

20:53.590 --> 20:53.730
haben.

20:54.330 --> 20:56.210
Vielleicht zeigt man nachher noch ein Beispiel, wenn wir die Zeit dazu

20:56.210 --> 20:56.430
haben.

20:57.310 --> 20:59.590
Und Sie sollten Ihre Tests immer vorausschauend schreiben.

21:00.490 --> 21:03.870
Das heißt, Ihre Tests sollten auch funktionieren, wenn sich Ihr Code

21:03.870 --> 21:04.210
ändert.

21:04.310 --> 21:07.990
Also wenn natürlich genau die Methodensignatur geändert wurde, dann

21:07.990 --> 21:09.190
müssen Sie Ihre Tests auch umschreiben.

21:09.190 --> 21:11.550
Aber wenn irgendwelche Sachen in Ihrer Software passiert sind, die

21:11.550 --> 21:14.230
eigentlich gar nicht direkt mit dem Test zu tun haben, dann sollte

21:14.230 --> 21:16.790
idealerweise der Test immer noch genauso laufen wie davor.

21:19.370 --> 21:23.250
Passiert mehr oder weniger automatisch, wenn man die oberen Themen

21:23.250 --> 21:23.810
einhält.

21:24.090 --> 21:27.190
Also isolierte Tests, kleine Tests, eine Eigenschaft abtesten.

21:27.430 --> 21:31.050
Dann passiert das mehr oder weniger automatisch, dass die auch auf

21:31.050 --> 21:32.930
Änderungen relativ gut reagieren im Code.

21:33.850 --> 21:36.650
Das Schema ist genau das, was Sie gerade gesehen haben.

21:36.650 --> 21:39.570
Sie initialisieren Ihre Eingabedaten.

21:40.770 --> 21:43.550
Sie rufen die Methode auf, die Sie testen wollen, oder unter Umständen

21:43.550 --> 21:44.930
mehrere Methoden hintereinander.

21:45.910 --> 21:50.930
Sie prüfen das Ergebnis dieser Methode oder Sie prüfen den Zustand des

21:50.930 --> 21:54.150
Programmes an dem Augenblick, wenn er öffentlich sichtbar ist, weil

21:54.150 --> 21:55.330
die Methoden public sind.

21:56.630 --> 22:00.430
Und schließlich, aber das ist häufig gar nicht so nötig, räumen Sie

22:00.430 --> 22:04.490
noch auf nach dem Test, um den Zustand wieder in Ordnung zu bringen

22:04.490 --> 22:07.410
danach, damit der nächste Test wieder von vorne anfangen kann.

22:10.930 --> 22:14.510
Bisschen anderes Thema, beziehungsweise kleiner Bruch an der Stelle.

22:15.690 --> 22:17.570
Was ist eigentlich ein Fehler in Software?

22:18.650 --> 22:20.590
Und da gibt es zwei Begriffe, die man unterscheiden muss.

22:20.690 --> 22:23.410
Das eine ist der Failure und das zweite ist ein Fault.

22:24.770 --> 22:29.470
Ein Failure ist ein Versagen des Programmes.

22:30.150 --> 22:32.770
Das heißt, wenn Sie das ausführen und wenn in diesem Augenblick die

22:32.770 --> 22:37.650
Exception geworfen wird, dann ist die Tatsache, dass entweder etwas

22:37.650 --> 22:40.030
Falsches rauskommt, oder dass eine Exception geworfen wurde, das ist

22:40.030 --> 22:40.670
Ihr Failure.

22:41.310 --> 22:44.390
Das ist Ihre Information, es ist was passiert, irgendwo in diesem

22:44.390 --> 22:46.730
Programm, irgendwas, was ich nicht erwartet hätte, was so nicht hätte

22:46.730 --> 22:47.310
sein sollen.

22:50.150 --> 22:52.490
Es reicht von der Spezifikation ab, genau das, was wir am Anfang

22:52.490 --> 22:53.230
gesagt haben.

22:55.230 --> 22:57.230
Sie müssen es ausführen, um das rauszufinden.

22:57.850 --> 22:59.910
Das ist der Witz an der ganzen Sache, Sie führen es aus und es

22:59.910 --> 23:02.770
passiert etwas Negatives.

23:03.570 --> 23:06.370
Der Fault, das ist quasi die Ursache dazu.

23:07.310 --> 23:09.630
Der Fault passiert nicht, der ist in der Software da.

23:10.370 --> 23:14.670
Das ist die Stelle, an der Sie als Programmierer oder irgendein

23:14.670 --> 23:18.670
anderer Programmierer einen Fehler gemacht hat und irgendwas Falsches

23:18.670 --> 23:19.330
hingetippt hat.

23:19.390 --> 23:21.290
Was nicht das tut, was er dachte, was es tut.

23:22.250 --> 23:24.390
Das ist der eine Schritt im Programm.

23:25.030 --> 23:27.090
Vielleicht sind es auch mehrere, muss nicht zwingend einer sein, aber

23:27.090 --> 23:29.950
das ist die Stelle im Programm, die falsch ist.

23:32.630 --> 23:35.130
Meistens ist es die Ursache für den Fault.

23:35.410 --> 23:38.530
Aber es kann auch durchaus sein, dass Sie mehr als einen Fehler im

23:38.530 --> 23:42.210
Programm haben und das, was Sie da entdeckt haben, wirklich

23:42.210 --> 23:42.750
feststellen.

23:43.250 --> 23:46.830
Sie haben einen Fehler, es ist ein Failure aufgetreten, Sie gucken

23:46.830 --> 23:50.570
sich das Programm an, Sie schauen sich den Programmcode an, Sie

23:50.570 --> 23:53.570
stolpern über eine Stelle und sagen, das kann jetzt nicht richtig

23:53.570 --> 23:54.550
sein, da stimmt was nicht.

23:55.630 --> 23:58.130
Das heißt nicht zwingend, dass das genau die Stelle ist, die dann zu

23:58.130 --> 24:02.050
dem Fehler führt, zu dem Fault oder zu dem Failure führt, den Sie

24:02.050 --> 24:02.810
beobachtet haben.

24:03.790 --> 24:09.770
Es kann auch sein, dass solche Faults im Programm sind und überhaupt

24:09.770 --> 24:10.690
gar nicht entdeckt werden.

24:11.130 --> 24:16.070
Entweder, weil der Fall nie ausgeführt wurde, indem der Fehler

24:16.070 --> 24:19.730
auftritt, weil es dafür keinen Test gibt und kein realer Kunde jemals

24:19.730 --> 24:20.710
das ausprobiert hat.

24:20.710 --> 24:23.430
Und dann passiert erstmal nichts.

24:23.570 --> 24:25.990
Das kann einem jederzeit explodieren, das kann jederzeit sein, dass es

24:25.990 --> 24:28.470
dann doch plötzlich passiert, wenn jemand eine andere Anforderung hat.

24:28.870 --> 24:32.530
So wie zum Beispiel bei dem Bestrahlungsgerät, die Leute mit der Zeit

24:32.530 --> 24:34.910
schneller geworden sind und plötzlich Fehler aufgetreten sind, die am

24:34.910 --> 24:36.290
Anfang nicht aufgetreten sind.

24:37.390 --> 24:40.830
Es kann aber auch sein, dass es gar nicht möglich ist, dass der Fehler

24:40.830 --> 24:41.750
ausgelöst wird.

24:42.110 --> 24:44.930
Zum Beispiel, weil es in der Methode ist, die nur durch andere

24:44.930 --> 24:48.630
Methoden aufgerufen werden und die anderen Methoden zufälligerweise,

24:48.690 --> 24:53.110
nicht bedacht, zufälligerweise diese Methode nie so aufrufen, dass der

24:53.110 --> 24:53.750
Fehler auftritt.

24:54.930 --> 24:58.030
Wenn die Methode spezifiziert, dass dieser Fall so sich verhalten

24:58.030 --> 25:01.130
soll, dann ist das sozusagen in Ordnung.

25:01.230 --> 25:04.690
Aber wenn die Methode in ihrer Spezifikation ein anderes Verhalten

25:04.690 --> 25:07.810
vortäuscht, dann ist das trotz allem Fehler, auch wenn der Fehler im

25:07.810 --> 25:10.350
Gesamtprogramm dann nicht mehr auftreten kann.

25:12.810 --> 25:16.190
Grob kann man sagen, bei den beiden Begriffen, Fault ist die Ursache,

25:16.690 --> 25:18.650
Failure ist die Auswirkung davon.

25:21.950 --> 25:24.270
Und allgemein geht es, wenn Sie wissen, dass ein Failure aufgetreten

25:24.270 --> 25:27.490
ist, dann den Fault zu finden, die Stelle an der es schief geht, ist

25:27.490 --> 25:29.890
die halbe Arbeit bei der ganzen Sache.

25:31.630 --> 25:32.770
Hier machen wir ein Beispiel.

25:47.910 --> 25:51.530
Wir haben hier ein Programm, das soll...

25:51.530 --> 25:53.470
Moment, hier habe ich eine Spezifikation.

25:54.710 --> 25:56.110
Lesen Sie sich das einfach ganz kurz durch.

25:57.390 --> 25:58.370
Das ist das Programm nochmal.

25:59.230 --> 26:00.190
Hier ist der Test dazu.

26:01.050 --> 26:03.390
R gleich gleich 5 ist das, was wir erwarten würden.

26:03.990 --> 26:08.490
Tatsächlich passiert aber ein Failure hier.

26:09.070 --> 26:10.450
Das ist der Failure, da unten.

26:10.450 --> 26:13.610
R ist gleich 4 an der Stelle.

26:14.970 --> 26:19.430
Und die Frage an Sie ist jetzt, wo tritt der Fehler auf im

26:19.430 --> 26:20.010
Programmcode?

26:22.050 --> 26:24.270
Sie können auf Socrative drauf, das kennen Sie ja schon.

26:25.050 --> 26:28.450
Raum PROC 1314, Antworten A bis E.

26:31.490 --> 26:31.750
E?

26:34.430 --> 26:36.650
Relativ viele unterschiedliche Meinungen.

26:37.690 --> 26:40.410
Ihr seht noch ein bisschen was, 4 Stück sind noch beschäftigt.

26:49.680 --> 26:51.360
Wir machen mal hier drüben weiter.

26:53.700 --> 26:54.560
Da ist ein Fault.

26:55.500 --> 26:56.620
Da ist ein Fehler im Programm.

26:58.000 --> 27:00.900
Die Spezifikation sagt, wir fangen bei Index P an.

27:01.760 --> 27:03.940
Tatsächlich fangen wir in der Schleife aber bei Index 0 an.

27:05.360 --> 27:07.680
Ist natürlich nicht das, was die Spezifikation sagt.

27:07.680 --> 27:10.960
Und es ist relativ einfach sich vorzustellen, wann das schief geht.

27:11.600 --> 27:14.080
Ist aber nicht konkret der Testfall hier.

27:14.340 --> 27:14.700
Tatsächlich.

27:14.880 --> 27:16.260
Also da ist definitiv ein Fehler im Programm.

27:17.860 --> 27:19.520
Nicht der Fehler, den wir erwarten.

27:20.920 --> 27:22.500
Dann haben wir ein Fault 2 hier.

27:23.020 --> 27:26.820
Wenn man genauer liest, sieht man, da steht Return P. Das sollte aber

27:26.820 --> 27:27.460
eigentlich I sein.

27:27.800 --> 27:29.360
P wird in der Funktion nie verändert.

27:29.560 --> 27:31.940
Das heißt, was wir zurückgeben, ist direkt das Argument, das wir oben

27:31.940 --> 27:32.680
reingesteckt haben.

27:32.680 --> 27:35.560
Also für den Test wäre das immer P gleich 4.

27:36.120 --> 27:37.740
Dann gibt das Ding natürlich 4 zurück.

27:38.800 --> 27:41.740
Das ist jetzt glaube ich auch schon direkt die Stelle, die Hilfe in

27:41.740 --> 27:42.860
den Fehler sucht.

27:44.120 --> 27:46.440
Haben wir aber auch noch einen dritten Fehler drin.

27:47.820 --> 27:49.800
Ebenfalls in Zeile...

27:49.800 --> 27:50.660
Was ist das?

27:53.320 --> 27:53.620
3.

27:54.940 --> 27:57.860
Das Problem hier...

27:57.860 --> 28:00.960
Wir laufen bis zum Element A.Length.

28:02.100 --> 28:03.560
6 Elemente hier unten drin.

28:04.240 --> 28:09.120
A von 6 ist eins nach dem fünften Element.

28:09.240 --> 28:10.140
Das existiert nicht mehr.

28:10.360 --> 28:13.440
Das ist ein ArrayIndexOutOfBoundsException, wie da geworfen würde.

28:13.740 --> 28:17.840
Wird aber auch von diesem Testfall gar nicht erreicht, weil er gibt ja

28:17.840 --> 28:20.140
vorher schon einen Wert zurück.

28:20.360 --> 28:21.680
Das passiert hier gar nicht.

28:22.040 --> 28:26.940
Das heißt, Fault 2 ist tatsächlich der Fehler, der wirklich den Fehler

28:26.940 --> 28:30.100
führt, den wir hier beobachtet haben.

28:31.900 --> 28:34.700
Aber man sieht schon, ein Testfall reicht offensichtlich gar nicht

28:34.700 --> 28:36.320
aus, um hier alle Faults zu finden.

28:36.680 --> 28:37.300
Das ist das erste.

28:37.700 --> 28:40.640
Der Testfall reicht aus, um Fault 2 zu finden.

28:41.440 --> 28:46.240
Wenn man den behebt, würde man mit dem Test auch Fault 1 finden, aber

28:46.240 --> 28:47.940
man kann an der Stelle nicht Fault 3 finden.

28:48.040 --> 28:50.820
Das heißt, um hier alle Faults zu finden, sollte man eigentlich schon

28:50.820 --> 28:51.900
mehrere Tests haben.

28:55.480 --> 28:57.420
Was ist Testen nicht?

28:59.760 --> 29:01.500
Das ist keine Fehlerlokalisierung.

29:02.080 --> 29:05.920
Also dieser Schritt von, ich habe einen Failure und ich will wissen,

29:05.980 --> 29:10.220
was der Fault dazu ist, das ist FaultLocalization.

29:10.460 --> 29:13.220
Das ist auch wichtig und das ist auch nicht ganz einfach.

29:13.640 --> 29:14.800
Aber es ist nicht der Punkt.

29:15.280 --> 29:17.960
Auch den Fehler dann zu beheben, ist nicht Teil des Testens.

29:18.120 --> 29:21.540
Teil des Testens ist nur festzustellen, dass da ein Failure auftritt.

29:22.320 --> 29:25.180
In dem Augenblick, in dem Sie den gefunden haben, als Software-Tester,

29:25.620 --> 29:26.980
ist Ihre Aufgabe eigentlich erledigt.

29:28.840 --> 29:29.560
Faire Übungsaufgaben?

29:29.800 --> 29:30.440
Natürlich nicht.

29:30.800 --> 29:32.300
Da müssen Sie die Schritte hier auch noch machen.

29:32.440 --> 29:35.460
Klar, reicht nicht zu sagen, hier ist mein Programm, ich weiß, da ist

29:35.460 --> 29:38.160
ein Fehler drin, der bricht dann und dann auf, aber ich ignoriere ihn,

29:38.380 --> 29:39.480
korrigiert halt einfach mal.

29:40.180 --> 29:43.440
Wenn Sie gar nichts hinkriegen, um den Fehler zu finden, ist das auch

29:43.440 --> 29:46.340
schon mal hilfreicher, als gar nicht zu sagen, dass man den Fehler

29:46.340 --> 29:46.880
erkannt hat.

29:47.220 --> 29:49.260
Aber grundsätzlich ist es natürlich immer besser, den Fehler auch

29:49.260 --> 29:50.420
wirklich zu beheben.

29:51.120 --> 29:54.860
Was sind andere Methoden, die das selber erreichen?

29:55.720 --> 29:56.800
Statische Code-Analyse.

29:57.440 --> 30:01.640
Also, dass man ein Programm über das Programm laufen lässt, sich das

30:01.640 --> 30:05.140
Programm anschauen lässt und das Programm sagt einem dann, ob da ein

30:05.140 --> 30:06.200
Fehler drin ist oder nicht.

30:06.200 --> 30:08.460
Checkstyle ist so ein Tool.

30:08.820 --> 30:12.020
Checkstyle geht in erster Linie auf syntaktische Sachen raus, aber oft

30:12.020 --> 30:16.320
genug gibt es einen Hinweis, da ist vielleicht was falsch, das ist

30:16.320 --> 30:18.520
vielleicht nicht so gedacht gewesen hier.

30:20.580 --> 30:24.400
Es gibt aber noch interessantere Find-Bugs in Java, was eben ein

30:24.400 --> 30:28.020
bisschen mehr auf semantischer Ebene einem sagt, wo Fehler sein

30:28.020 --> 30:28.460
könnten.

30:29.760 --> 30:34.060
Und es gibt richtig schwergewichtige Methoden, die mit mathematischen

30:34.060 --> 30:39.040
Beweisen arbeiten, die den CASO zum Beispiel entwickelt, das Key

30:39.040 --> 30:43.280
-System, bei dem man sehr ausführlich, sehr formal spezifizieren kann,

30:43.420 --> 30:47.440
wie das Programm sich verhalten soll und dann mathematische Beweise

30:47.440 --> 30:51.120
führen kann über dieses Programm und damit zeigen kann, dass das

30:51.120 --> 30:52.980
Programm tatsächlich keinen Fehler enthält.

30:54.780 --> 30:58.240
Und die zweite Sache, was Tests auch nicht sind, sind Reviews.

30:58.500 --> 31:01.520
Also, dass man sich nochmal an den Code setzt und von oben bis unten

31:01.520 --> 31:01.900
durchguckt.

31:01.960 --> 31:04.300
Auch das ist statisch, auch dabei wird der Code nicht ausgeführt.

31:05.420 --> 31:09.000
Der Code wird angeschaut und man versucht ihm anzusehen, ob Fehler

31:09.000 --> 31:09.880
drin sind oder nicht.

31:10.240 --> 31:12.780
Und das ist auch eine wichtige Methode, weil diese Methode nochmal

31:12.780 --> 31:16.320
ganz andere Fehler finden kann, als vielleicht auch Tests finden

31:16.320 --> 31:16.660
können.

31:17.240 --> 31:20.320
Was man zum Beispiel nicht finden kann mit Tests, ist, wenn das

31:20.320 --> 31:23.660
Programm zwar das Richtige tut, es aber auf eine Art und Weise tut,

31:23.720 --> 31:26.960
die einfach sehr, sehr unschön ist und die dann später Probleme gibt

31:26.960 --> 31:28.200
mit der Erweiterbarkeit des Codes.

31:29.480 --> 31:33.200
Dafür muss man immer noch den Code reviewen und anschauen und Menschen

31:33.200 --> 31:35.940
drüber schauen lassen, der sagt, das sieht gut aus, das ist eine gute

31:35.940 --> 31:36.940
Architektur zum Beispiel.

31:37.900 --> 31:40.560
Fehlerfreiheit ist ja nicht das einzige Kriterium für gute Software.

31:41.100 --> 31:43.500
Aber auch funktionale Fehler kann man natürlich mit Reviews durchaus

31:43.500 --> 31:43.860
finden.

31:44.620 --> 31:47.660
Z ersetzt aber niemals die Tests an sich.

31:48.220 --> 31:50.140
Bei einem Review müssten Sie jedes Mal wieder durchführen.

31:50.640 --> 31:52.820
Wenn Sie die Tests einmal geschrieben haben, können Sie für alle

31:52.820 --> 31:57.440
Softwareversionen, die Sie in Zukunft schreiben, dieselben Tests

31:57.440 --> 31:59.700
nochmal laufen lassen und schauen, ob sich irgendwelche Änderungen

31:59.700 --> 32:00.220
ergeben haben.

32:00.460 --> 32:02.440
Wenn Sie das mit Reviews machen, wird das sehr schnell sehr teuer und

32:02.440 --> 32:03.000
aufwendig.

32:04.220 --> 32:05.660
Warum ist Testen so schwierig?

32:06.520 --> 32:08.920
Was macht einen Testfall zu einem guten Testfall?

32:09.580 --> 32:11.080
Die Fähigkeit, Fehler zu finden.

32:12.440 --> 32:17.220
Klingt trivial, aber oft genug schreibt man Tests, die einfach gar

32:17.220 --> 32:19.200
nicht dazu geeignet sind, wirkliche Fehler zu finden.

32:20.380 --> 32:21.380
Scheintestfälle eigentlich.

32:21.380 --> 32:27.640
Den dritten Testfall, der genau den gleichen Testfall abdeckt, mit ein

32:27.640 --> 32:28.420
bisschen anderen Daten.

32:28.520 --> 32:30.000
Das bringt nicht viel Neues.

32:30.620 --> 32:33.860
Oder er findet überhaupt gar keinen Fehler oder kann gar keinen Fehler

32:33.860 --> 32:36.640
finden, weil er einfach nicht viel Sinnvolles tut.

32:37.080 --> 32:39.520
Oder er testet nicht die Spezifikationen ab.

32:39.600 --> 32:41.700
Das sagt einem dann auch nicht, ob das ein Fehler ist oder nicht.

32:44.140 --> 32:49.220
Was würde das heißen allerdings für ein fehlerfreies Programm?

32:49.980 --> 32:53.340
Wenn das Kriterium für einen guten Testfall ist, dass er Fehler

32:53.340 --> 32:59.180
findet, dann würde das heißen, dass es für ein fehlerfreies Programm

32:59.180 --> 33:01.320
keine guten Tests gibt.

33:02.100 --> 33:03.780
Das ist auch irgendwie Unfug.

33:05.040 --> 33:07.440
Tests müssen immer sinnvoll sein.

33:07.540 --> 33:10.560
Es kann nicht sein, dass es keine guten Tests für das Programm gibt.

33:10.860 --> 33:14.400
Wir wollen ja auch Tests haben, wenn sich das Programm später ändert,

33:14.460 --> 33:16.800
dass wir dann diese Änderung nochmal überprüfen können.

33:16.800 --> 33:21.700
Das heißt, eher richtig ist vielleicht, es sollte wahrscheinliche

33:21.700 --> 33:22.700
Fehler finden können.

33:23.040 --> 33:26.420
Wenn ich das Programm leicht abändere, verbessere, wenn dann ein

33:26.420 --> 33:29.140
Fehler auftritt, dass es das auch immer noch abfinden kann.

33:29.880 --> 33:32.620
Und es sollte das Ganze mit angemessenem Aufwand machen.

33:33.740 --> 33:36.420
Wenn Sie so viel Energie in diese Tests investieren, dass Sie das

33:36.420 --> 33:39.500
Produkt erst Jahre später auf den Markt kriegen, dann ist das auch

33:39.500 --> 33:41.000
nicht sonderlich zielführend.

33:41.660 --> 33:43.340
Dabei müssen Sie immer zwei Kosten abwägen.

33:43.340 --> 33:46.540
Das erste ist die Kosten, die es verursacht, dass Sie diese Tests

33:46.540 --> 33:50.900
schreiben, ausführen, anpassen müssen, an die nächste Version der

33:50.900 --> 33:52.400
Software vielleicht auch bewerten.

33:54.300 --> 33:57.300
Das zweite sind die Kosten, die es verursacht, wenn ein Fehler

33:57.300 --> 33:57.900
auftritt.

33:59.240 --> 34:02.160
Also im Fall von Toyota zum Beispiel mit den Gaspedalen.

34:03.040 --> 34:08.580
Der Imageschaden für Toyota ist in Geldbeträgen schwierig

34:08.580 --> 34:11.300
einzuschätzen, aber extrem hoch.

34:11.300 --> 34:17.200
Toyota war davor bekannt für zuverlässige Autos, für solides

34:17.200 --> 34:20.340
Engineering und plötzlich passiert das, das Auto gibt Gas.

34:20.820 --> 34:23.720
Es gab, glaube ich, auch mindestens einen Todesfall bei der ganzen

34:23.720 --> 34:24.060
Sache.

34:24.600 --> 34:25.920
Der Imageschaden ist gewaltig.

34:26.620 --> 34:30.260
Also die Kosten, einen Fehler nicht gefunden zu haben, die darf man

34:30.260 --> 34:33.580
nicht unterschätzen, auch wenn sie schwierig einzuschätzen sind und zu

34:33.580 --> 34:34.240
bewerten sind.

34:36.080 --> 34:41.220
Aus Managementgründen sollten Sie so klein wie möglich, aber so groß

34:41.220 --> 34:42.880
wie nötig Test-Suites haben.

34:43.200 --> 34:46.500
Das heißt, wenn Sie es hoffnungslos übertreiben beim Testschreiben,

34:46.580 --> 34:49.320
einfach nur um sehr, sehr viele zu haben, haben Sie später Probleme,

34:49.440 --> 34:51.600
die Tests zu aktualisieren und überhaupt zu bewerten.

34:51.880 --> 34:54.860
Wenn Sie einen Test haben, der eine Eigenschaft abdeckt und diese

34:54.860 --> 34:57.980
Eigenschaft ist bei einer Version nicht gegeben, dann sehen Sie an

34:57.980 --> 34:59.940
diesem einen Test ganz genau, das ist diese Eigenschaft.

35:00.100 --> 35:02.980
Wenn Sie zehn Tests haben, die dasselbe abdecken, dann kann es unter

35:02.980 --> 35:04.780
Umständen einfach ein bisschen unübersichtlicher werden.

35:08.220 --> 35:12.340
Das nächste ist, dass ein Test auch es einfach machen sollte, den

35:12.340 --> 35:13.680
Fehler dann tatsächlich zu finden.

35:14.320 --> 35:18.620
Deswegen auch von Anfang an die Kriterien, kurze Tests auf eine

35:18.620 --> 35:22.640
Eigenschaft, prägnant, gut dokumentiert, einfach damit man leichter

35:22.640 --> 35:25.120
die Ursache für den Fehler finden kann.

35:27.960 --> 35:30.420
Wichtig ist eben immer Spezifikation.

35:31.340 --> 35:35.120
Mit Übungsaufgaben ist die Spezifikation sozusagen das Übungsblatt,

35:35.200 --> 35:35.940
das Sie erfüllen müssen.

35:36.300 --> 35:39.780
Dagegen müssen Sie testen, daraus müssen Sie sich Ihre Testfälle

35:39.780 --> 35:40.200
überlegen.

35:42.800 --> 35:47.620
Wenn Sie keine Spezifikation haben, dann können Sie immer noch testen,

35:48.400 --> 35:49.700
ob das Programm nicht abstürzt.

35:50.900 --> 35:55.060
Das heißt, Sie können anschauen, Sie werfen einfach Eingaben an das

35:55.060 --> 35:58.300
Programm, die möglicherweise unerwartet sind.

35:58.460 --> 36:01.000
Sie versuchen, sich mal in die Position des Entwicklers

36:01.000 --> 36:01.760
reinzuversetzen.

36:02.140 --> 36:04.400
Belegen Sie sich, was würde ich jetzt vergessen?

36:04.620 --> 36:05.440
Was vergesse ich gerne?

36:05.700 --> 36:06.560
Was vergesse ich oft?

36:06.680 --> 36:07.480
Wo mache ich oft einen Fehler?

36:08.140 --> 36:12.920
Und dann kommen Sie so auf so Sachen wie, das Integer, das Parsen von

36:12.920 --> 36:16.460
Integers aus Strings, da habe ich vergessen abzufangen, was ich machen

36:16.460 --> 36:18.800
muss, wenn das überhaupt gar kein Integer ist, der an der Stelle

36:18.800 --> 36:19.200
steckt.

36:19.200 --> 36:21.900
Das sind so Sachen, die einem gerne passieren und die man auch absolut

36:21.900 --> 36:22.620
testen sollte.

36:23.500 --> 36:25.980
Und das können Sie auch machen, wenn Sie keine Spezifikation haben.

36:26.840 --> 36:28.420
Aber es ist halt sehr oberflächlich.

36:29.100 --> 36:32.040
Also es testet dann halt nicht, ob das Programm das Richtige tut, wenn

36:32.040 --> 36:33.260
eben kein Exception passiert.

36:35.360 --> 36:35.760
Teststrategien.

36:36.460 --> 36:38.460
Wie wähle ich meine Testfälle aus?

36:39.780 --> 36:42.220
Da gibt es eigentlich zwei große, unterschiedliche Ansätze.

36:42.300 --> 36:43.740
Das erste ist datenbasiert.

36:43.740 --> 36:48.220
Das heißt, Sie schauen sich die Eingaben an und überlegen sich, was

36:48.220 --> 36:52.800
für Eingaben könnten jetzt gute Testfälle sein, was sind so die

36:52.800 --> 36:56.660
normalen Fälle, die Gruppen von Fällen, die ich habe.

36:56.740 --> 36:58.540
Also wir hatten das immer am Anfang mit den Dreiecken.

36:59.480 --> 37:03.120
Dann suchen Sie quasi jede Gruppe raus, die Gleichschenklingen, die

37:03.120 --> 37:07.120
Gleichseitigen, die Weder-Noch, die Ungültigen von jeder möglichen

37:07.120 --> 37:07.960
Art, die es da gab.

37:08.980 --> 37:11.020
Das zweite ist aber auch Grenzwerte.

37:11.020 --> 37:17.520
Also Werte, die in der Informatik, vielleicht auch der Mathematik

37:17.520 --> 37:20.380
gerne, eine besondere Eigenschaft haben oder ein besonderes Verhalten

37:20.380 --> 37:20.680
haben.

37:21.140 --> 37:25.020
Das ist zum Beispiel bei Integern, ist das immer ganz gut, Minus 101,

37:26.100 --> 37:30.160
Integer Max Value, also der größtmögliche Integerwert, den man

37:30.160 --> 37:30.940
darstellen kann.

37:32.240 --> 37:35.780
Einfach als ein möglichst großer Wert, Integer Min Value natürlich

37:35.780 --> 37:36.220
auch.

37:36.880 --> 37:40.720
Und, Frau Lorte, Grenzwerte natürlich nicht vergessen, trotzdem immer

37:40.720 --> 37:44.820
noch oben die ganz normalen Fälle in Betracht halten, also als normale

37:44.820 --> 37:48.840
Zahl, 42 oder sowas, nur um irgendwas anderes auch noch ausprobiert zu

37:48.840 --> 37:50.680
haben und nicht nur Grenzwerte abgedeckt zu haben.

37:51.080 --> 37:56.020
Bei Listen immer gut, eine leere Liste, eine Nullreferenz, eine

37:56.020 --> 38:00.800
einelementige Liste oder eine relativ normale Liste mit einer Handvoll

38:00.800 --> 38:01.580
Elementen drin.

38:02.840 --> 38:07.120
Arrays derselbe, Nullreferenzen, Arrays der Länge 0, der Länge 1.

38:08.800 --> 38:11.960
Die zweite große Gruppe sind Programmbasierte, das heißt in dem Fall

38:11.960 --> 38:15.720
schauen Sie sich das Programm an, den Programmcode, und überlegen Sie

38:15.720 --> 38:18.580
sich daraufhin dann, was gut wäre zum Testen.

38:19.120 --> 38:22.320
Das erste ist sozusagen Blackbox-Testing, nennt sich das.

38:22.360 --> 38:24.540
Das Programm ist eine schwarze Box, Sie können da nicht reinschauen

38:25.200 --> 38:28.900
und Sie überlegen sich einfach anhand der Spezifikationen und der

38:28.900 --> 38:31.240
möglichen Eingabedaten, was könnte hier gut funktionieren.

38:31.580 --> 38:34.740
Das andere, die Programmbasierte, das ist Whitebox-Testing.

38:34.840 --> 38:38.380
Da dürfen Sie in das Programm reingucken und sich überlegen, wie

38:38.380 --> 38:40.100
könnte ich jetzt das Programm zum Absturz bringen?

38:40.280 --> 38:41.140
Was sind so Stellen?

38:41.260 --> 38:44.460
Oh, da ist ein bedingter Sprung an If-Then-Else zum Beispiel.

38:44.780 --> 38:48.060
Da könnte ich doch mal versuchen, vielleicht in den Else-Zweig

38:48.060 --> 38:50.660
reinspringen zu lassen und dann was Unerwartetes zu machen.

38:54.720 --> 38:57.940
Kriterien, nach denen Sie da gute Testfälle auswählen oder wie Sie

38:57.940 --> 39:00.560
Ihre Testfälle auswählen sollen, sind dann Coverage-Kriterien.

39:01.040 --> 39:05.060
Das heißt, Sie versuchen möglichst viel Verhalten abzudecken Ihres

39:05.060 --> 39:05.640
Programmes.

39:06.200 --> 39:08.660
Und das sehen Sie dem Programm an, was Sie da tun müssen.

39:09.060 --> 39:11.720
Also eine Möglichkeit ist zum Beispiel, dass Sie versuchen, dass jede

39:11.720 --> 39:13.960
Zeile in Ihrem Programm einmal ausgeführt wird.

39:14.660 --> 39:18.880
Das heißt, Sie schreiben Ihre Testfälle ganz gezielt so, dass wenn Sie

39:18.880 --> 39:22.200
da eine Methode haben, dass dieser Testfäller versorgt, dass diese

39:22.200 --> 39:23.760
Methode auch wirklich aufgerufen wird.

39:24.420 --> 39:27.980
Und wenn eine Methode eben ein If-Then-Else drin hat, dann sorgen Sie

39:27.980 --> 39:30.800
dafür, dass ein Testfall ein If und der andere ein Else abdeckt,

39:31.060 --> 39:33.140
sodass jede Zeile mindestens einmal vorkommt.

39:34.680 --> 39:38.720
Zweite Möglichkeit, jede Bedingung muss einmal wahr und einmal falsch

39:38.720 --> 39:39.080
sein.

39:40.600 --> 39:43.540
Das heißt, das If-Then-Else muss einmal zu True und einmal zu False

39:43.540 --> 39:43.900
ausgewertet werden.

39:43.960 --> 39:46.380
Das ist ein bisschen anders, als wenn Sie versuchen, jede Zeile zu

39:46.380 --> 39:46.620
machen.

39:46.860 --> 39:52.700
Also zum Beispiel würde das heißen, dass in manchen Fällen Sie über

39:52.700 --> 39:55.580
einen anderen Weg an dieselbe Stelle kommen könnten.

40:02.120 --> 40:05.380
Hier nicht mehr aufgeführt, es gibt noch andere Möglichkeiten, zum

40:05.380 --> 40:10.040
Beispiel wenn Sie eine If-Bedingung haben, bei der Sie über Und oder

40:10.040 --> 40:15.560
Oder mehrere Bedingungen hintereinander schreiben, dann wird ein Java

40:15.560 --> 40:16.780
Shortcut Evaluation gemacht.

40:16.920 --> 40:19.500
Das heißt, die erste wird ausgewertet und wenn damit schon feststeht,

40:19.500 --> 40:21.900
ob die Gesamtbedingung war es oder falsch, dann wird der Rest gar

40:21.900 --> 40:22.800
nicht mehr ausgewertet.

40:23.140 --> 40:25.360
Das kann man als impliziten Sprung sehen.

40:25.480 --> 40:30.160
Auch da kann man sich dafür entscheiden, entweder alle Varianten zu

40:30.160 --> 40:31.480
behandeln oder eben nur einer davon.

40:31.840 --> 40:37.300
Zum Beispiel, dass man in diese Schleife oder in einen If-Then-Block

40:37.300 --> 40:41.180
reinspringt über den ersten Teil der Bedingung, den zweiten Teil der

40:41.180 --> 40:44.100
Bedingung, den dritten Teil der Bedingung, wenn es ein Oder ist zum

40:44.100 --> 40:45.660
Beispiel, wo nur eins von drei gelten muss.

40:45.660 --> 40:50.920
Da kann man noch wesentlich aufwendigere Konzepte sich überlegen, wie

40:50.920 --> 40:53.340
man dafür sorgt, dass möglichst viel abgedeckt wird.

40:53.580 --> 40:55.860
Es ist auf jeden Fall sinnvoll, sowas zu machen, wenn man den

40:55.860 --> 40:58.700
Programmcode hat, was nicht zwingend immer gegeben ist.

41:02.420 --> 41:04.580
Damit kommen wir zum zweiten Teil, Assertions.

41:05.000 --> 41:07.460
Und das ist genau dieses Konstrukt, das ich am Anfang einmal gezeigt

41:07.460 --> 41:07.760
hatte.

41:11.460 --> 41:15.340
Dieses Assert hier, das überprüft, ob die Eigenschaft zu dem Zeitpunkt

41:15.340 --> 41:15.640
gilt.

41:16.680 --> 41:21.640
Das ist ein Java-Schlüsselwort, ein eingebautes Sprachfeature, das wir

41:21.640 --> 41:22.600
nutzen können für sich.

41:24.460 --> 41:29.060
Was es macht ist, im Prinzip, es prüft diese Bedingung, die da hinten

41:29.060 --> 41:32.120
dran steht, zu dem Zeitpunkt, wenn das Ding ausgeführt wird.

41:32.440 --> 41:35.400
Das heißt, sie führen den Test aus, weisen die Werte zu, führen die

41:35.400 --> 41:38.180
Methode aus und prüfen dann die Eigenschaft.

41:38.640 --> 41:42.180
Das können sie, wie es hier gemacht ist, in Testfälle einfach

41:42.180 --> 41:42.700
reinschreiben.

41:42.880 --> 41:45.600
Für jeden einzelnen Testfall prüfen sie am Schluss die Eigenschaften

41:45.600 --> 41:45.960
damit.

41:47.820 --> 41:52.360
Syntax, Assert, Schlüsselwort und dann die Bedingung dranschreiben,

41:52.760 --> 41:53.480
ein Bullshit-Ausdruck.

41:54.240 --> 41:56.880
Oder alternativ mit einem Doppelpunkt und einer detaillierten

41:56.880 --> 41:57.960
Fehlermeldung hintendran.

41:58.560 --> 42:01.240
Eigentlich ist das meistens vorzuziehen, außer für triviale Fälle.

42:01.240 --> 42:05.080
Was der Benutzer dann nämlich sieht, ist ein Stacktrace mit dieser

42:05.080 --> 42:06.300
Information dran geschrieben.

42:06.720 --> 42:09.540
Und die beschreibt ihm dann, was wirklich schiefgegangen ist an der

42:09.540 --> 42:09.800
Stelle.

42:12.360 --> 42:17.120
Allgemein gilt, wir wollen in unserem Code Zusicherungen machen, was

42:17.120 --> 42:18.300
zu einem beliebigen Zeitpunkt geht.

42:18.360 --> 42:20.360
Wir wollen festhalten, was gilt.

42:20.740 --> 42:23.120
Eine Methode ist eben genau dieses Search-Stichwort.

42:23.500 --> 42:26.460
Das heißt, wir können sagen, in dem Fall zum Beispiel, wenn wir das

42:26.460 --> 42:30.240
Skalarprodukt von zwei Vektoren berechnen, dass wir annehmen, dass zu

42:30.240 --> 42:32.980
diesem Zeitpunkt, wenn wir diese Methode aufrufen, die beiden Längen

42:32.980 --> 42:33.820
identisch sind.

42:34.560 --> 42:36.580
ThirdU.Length ist gleich V.Length.

42:38.280 --> 42:41.280
Wir können solche Zusicherungen aber auch umgangssprachlich

42:41.280 --> 42:42.020
formulieren.

42:43.020 --> 42:45.840
Das ist dann zum Beispiel diese Zeile hier, wo wir einfach als

42:45.840 --> 42:47.140
Kommentar das reinschreiben.

42:47.240 --> 42:51.820
Das kann jetzt natürlich nicht mehr von der Virtual Machine überprüft

42:51.820 --> 42:53.440
werden, ob das zu dem Zeitpunkt gilt.

42:53.560 --> 42:56.100
Das heißt, das ist einzig und allein eine Anmerkung für den

42:56.100 --> 42:56.720
Programmierer.

42:56.720 --> 43:00.160
Ich habe mir mal gedacht, dass an der Stelle doch eigentlich immer

43:00.160 --> 43:01.160
diese Eigenschaft gilt.

43:01.980 --> 43:05.020
Und das kann man dann als Programmierer auf der einen Seite prüfen, ob

43:05.020 --> 43:05.600
das gilt.

43:05.960 --> 43:06.980
Und wenn das gilt, ist das gut.

43:07.320 --> 43:09.940
Dann hat man die richtigen Annahmen getroffen und wahrscheinlich ist

43:09.940 --> 43:11.260
der Code dann auch gut.

43:12.820 --> 43:15.380
Man kann das aber auch nutzen in der weiteren Argumentation, wenn man

43:15.380 --> 43:17.820
sich den Programmcode danach anschaut und überlegt, wie geht es jetzt

43:17.820 --> 43:18.460
eigentlich weiter.

43:19.040 --> 43:20.920
Dann kann man sich die Zeile nochmal angucken und sagen, ach ja

43:20.920 --> 43:23.740
stimmt, das gilt ja an der Stelle immer.

43:23.740 --> 43:26.260
Das habe ich mir ja mal so überlegt gehabt.

43:28.540 --> 43:31.360
Im Allgemeinen gibt es drei große Gruppen von Zusicherungen.

43:31.460 --> 43:33.520
Das sind die Vorbedingungen, das ist das, was unmittelbar nach

43:33.520 --> 43:34.600
Funktionsaufruf gilt.

43:35.400 --> 43:37.320
Das ist eine ganz klassische Stelle, an der man das sagt.

43:37.400 --> 43:38.500
Das ist Teil der Spezifikation.

43:38.580 --> 43:39.840
Wie rufe ich die Methode auf?

43:39.900 --> 43:40.980
Was darf ich da reingeben?

43:41.320 --> 43:43.480
Das Argument, das ich reingebe, darf das zum Beispiel eine

43:43.480 --> 43:45.460
Nullreferenz sein oder ist das verboten?

43:46.360 --> 43:48.600
Das zweite ist, was gibt die Methode eigentlich zurück?

43:49.260 --> 43:53.140
Auch wieder ganz klassisch, kann die eine Nullreferenz zurückgeben

43:53.140 --> 43:56.160
oder muss da immer ein gültiges Objekt zurückgegeben werden?

43:56.240 --> 43:59.560
Das heißt, jemand der die Methode aufruft und das Objekt danach

43:59.560 --> 44:03.600
benutzt, muss der selber nochmal gucken, ist das Null oder kann er

44:03.600 --> 44:06.440
einfach davon ausgehen, weil die Methode ihm das garantiert hat, dass

44:06.440 --> 44:09.280
sie sagt, alles was ich hier zurückgebe, ist niemals Null.

44:10.020 --> 44:11.320
Und das dritte ist für Schleifen.

44:11.840 --> 44:13.440
Das ist eine Schleifen-Invariante.

44:13.640 --> 44:16.680
Das heißt, die Idee dahinter ist, dass diese Eigenschaft bei jedem

44:16.680 --> 44:17.820
Schleifen -Durchlauf gilt.

44:19.340 --> 44:21.520
Einmal am Anfang, einmal am Ende der Schleife, aber es muss immer

44:21.520 --> 44:21.880
gelten.

44:22.320 --> 44:25.420
In der Schleife kann das mal kurz kaputt gehen, aber sobald Sie die

44:25.420 --> 44:28.980
Schleifen -Iterationen abschließen, muss die Eigenschaft wieder

44:28.980 --> 44:29.340
gelten.

44:29.660 --> 44:32.500
Und das hilft ungemein dabei, sich ein bisschen konzeptionellen

44:32.500 --> 44:37.240
Gedanken zu machen, das macht die Schleife eigentlich genau und hilft

44:37.240 --> 44:40.000
sehr dabei, korrektere Programme zu schreiben an der Stelle.

44:42.260 --> 44:46.540
Wenn Sie Assert benutzen, ist das super praktisch, weil das eben

44:46.540 --> 44:48.420
wirklich automatisch überprüft wird.

44:48.540 --> 44:51.600
Wenn das nicht der Fall ist, stürzt das Programm ab an der Stelle.

44:52.460 --> 44:54.740
Das können Sie nicht nur im Test benutzen, das können Sie an jeder

44:54.740 --> 44:57.540
beliebigen Stelle im Prinzip hinschreiben und das sollten Sie auch

44:57.540 --> 45:01.160
großzügig nutzen, weil es Ihnen wirklich hilft, Ihre Programme

45:01.160 --> 45:01.740
korrekter zu machen.

45:01.740 --> 45:05.980
Und der Nachteil ist, Sie können wirklich auch nur Java-Syntax

45:05.980 --> 45:06.340
verwenden.

45:06.460 --> 45:09.980
Das heißt, was Sie da hinschreiben, muss in Java ausdrückbar sein, was

45:09.980 --> 45:11.460
nicht immer ganz einfach ist.

45:13.000 --> 45:16.960
Oder es wird unter Umständen teuer in der Laufzeit, was auch negativ

45:16.960 --> 45:17.540
sein kann.

45:18.820 --> 45:21.420
Die andere Alternative ist eben, das natürlich sprachlich hinzumachen.

45:21.560 --> 45:23.720
Da haben Sie alle sprachliche Freiheit, das auszudrücken.

45:23.840 --> 45:27.980
Da können Sie mehr mit ausdrücken normalerweise, aber es wird eben

45:27.980 --> 45:29.480
nicht mehr automatisch überprüft.

45:31.020 --> 45:34.320
Standardmäßig muss man allerdings aufpassen, gibt es eine Option

45:34.320 --> 45:35.280
Enable Assertions.

45:36.040 --> 45:40.760
Java bindet Strich EA und erst dann werden Assertions überhaupt

45:40.760 --> 45:41.460
überprüft.

45:41.720 --> 45:43.520
Standardmäßig werden sie nicht ausgewertet.

45:43.620 --> 45:45.500
Das heißt, Sie können Assertions in Ihren Code schreiben.

45:46.020 --> 45:50.160
Wenn Sie nicht Strich EA beim Aufruf angeben, dann passiert überhaupt

45:50.160 --> 45:51.060
gar nichts an der Stelle.

45:51.180 --> 45:55.140
Der Code wird optimiert, sodass die Prüfungen nicht gemacht werden und

45:55.140 --> 45:57.920
Sie würden sich wundern, warum da nichts passiert.

46:00.100 --> 46:02.840
Eine Frage gibt es noch, die relativ groß ist und wichtig ist zum

46:02.840 --> 46:03.580
Thema Assertions.

46:03.740 --> 46:07.520
Und das ist die Frage, wann benutze ich eigentlich Assertions und wann

46:07.520 --> 46:09.060
benutze ich Exceptions.

46:09.420 --> 46:11.040
Weil es beides relativ ähnlich ist.

46:11.400 --> 46:13.700
Es ist irgendwas passiert, was ich nicht erwartet hatte oder was so

46:13.700 --> 46:14.640
nicht hätte sein sollen.

46:15.100 --> 46:17.540
Und jetzt will ich signalisieren, irgendwas stimmt nicht.

46:18.420 --> 46:19.520
Es soll irgendwie anders weitergehen.

46:19.620 --> 46:20.340
Irgendwas soll jetzt passieren.

46:20.500 --> 46:21.700
Es soll eingegriffen werden.

46:23.160 --> 46:27.340
Assertions ist die typische Verwendung, dass der Programmierer sich

46:27.340 --> 46:31.200
Gedanken gemacht hat, was sollte an dem Zeitpunkt gelten und selber

46:31.200 --> 46:34.700
auch in der Hand hatte, dass das immer so gilt und plötzlich gilt das

46:34.700 --> 46:37.360
nicht mehr, weil er selber irgendwo einen Programmfehler drin hat.

46:39.320 --> 46:43.660
Dient auch zur Dokumentation, also auch wenn Sie Kommentare nutzen

46:43.660 --> 46:44.760
können zur Dokumentation.

46:45.060 --> 46:47.180
Assertions sind genauso Teil der Dokumentation.

46:47.180 --> 46:50.940
Sie kommunizieren, was eigentlich an diesem Zeitpunkt gelten sollte.

46:53.420 --> 46:56.660
Und ganz wichtig ist eigentlich, dass die Fehler, die Sie in

46:56.660 --> 47:00.680
Assertions abprüfen, zu der Laufzeit gar nicht mehr korrigierbar sind.

47:01.260 --> 47:02.420
Es ist irgendwas passiert.

47:03.100 --> 47:05.380
Sie wissen nur, es stimmt was nicht mehr.

47:05.760 --> 47:07.220
Das war nicht das, was ich erwartet hatte.

47:07.340 --> 47:11.540
Da ist eine Zahl, die ist nicht in meinem Wertebereich drin oder da

47:11.540 --> 47:14.940
ist eine Nullreferenz, wo keine hätte sein dürfen oder was ähnliches.

47:14.940 --> 47:18.240
Sie wissen jetzt, da stimmt was nicht und Sie haben aber keine

47:18.240 --> 47:21.540
Möglichkeit, jetzt noch irgendwie die Situation zu retten.

47:22.180 --> 47:25.360
Und Sie wissen aber gleichzeitig auch ganz genau, dass die Methode,

47:25.420 --> 47:27.960
die Sie aufgerufen hat, die möglicherweise ein anderer Programmierer

47:27.960 --> 47:30.400
geschrieben hat, dass der das auch nicht mehr retten kann.

47:31.780 --> 47:33.680
In Ihrem Programm selber ist irgendwas falsch.

47:33.760 --> 47:35.360
Ihr Zustand des Programmes ist falsch.

47:36.580 --> 47:37.540
Unwiederholbar falsch.

47:38.260 --> 47:39.220
Unreparierbar falsch.

47:40.080 --> 47:42.180
Wir können abschalten, wie gleich schon gesagt.

47:42.880 --> 47:43.720
So sieht das aus.

47:44.360 --> 47:47.880
Wir haben auch schon Beispiele für If and Exceptions.

47:48.260 --> 47:49.380
Das ist eben die andere Sache.

47:50.980 --> 47:54.060
Die würde man typischerweise zum Beispiel verwenden, nicht nur, aber

47:54.060 --> 47:57.080
typischerweise, um Benutzereingaben zu überprüfen.

47:58.140 --> 48:02.520
Also der Benutzer kann beliebige Zahlen zum Beispiel einer Methode

48:02.520 --> 48:06.320
übergeben und Sie würden an der Stelle überprüfen, ist die Zahl

48:06.320 --> 48:10.680
kleiner als 0, falls ja, dann ist das eine ungültige Zahl, dann wirft

48:10.680 --> 48:11.780
man Exception an der Stelle.

48:12.380 --> 48:13.820
Irgendwelche Sonderfälle in Allgemeinen.

48:14.120 --> 48:16.760
Der normale Fall sollte nicht mit Exceptions abgehandelt werden.

48:16.880 --> 48:20.080
Also Exceptions wirklich immer nur für Sonderfälle, für unerwartete

48:20.080 --> 48:20.740
Fälle nutzen.

48:21.720 --> 48:25.700
Der entscheidende Punkt ist, die Idee bei Exceptions ist, dass jemand

48:25.700 --> 48:26.700
anderes sie fängt.

48:27.560 --> 48:30.040
Man wirft sie, man sagt, es ist ein Fehler passiert, aber ich weiß

48:30.040 --> 48:32.940
nicht, was man jetzt machen soll, wie dieses Programm weiterlaufen

48:32.940 --> 48:33.240
soll.

48:33.240 --> 48:36.680
Und man wirft diese Exception und die Exception wird gefangen von

48:36.680 --> 48:40.040
jemandem, der sagt, ich weiß, was hier zu tun ist.

48:40.180 --> 48:42.240
Ich weiß, wie man die Situation retten kann, ich weiß, wie wir

48:42.240 --> 48:43.100
weitermachen können.

48:43.520 --> 48:45.440
Also wenn wir zum Beispiel ein Programm haben mit einer

48:45.440 --> 48:49.460
Dateneingabemaske und in der Maske kann man eine beliebige Zahl

48:49.460 --> 48:53.380
eingeben und in dieser Maske gibt man eine Zahl ein für eine viel zu

48:53.380 --> 48:54.360
hohe Bestrahlungsstärke.

48:55.060 --> 48:57.820
Dann wäre eine Möglichkeit, das abzufangen, dass man eben sagt, an der

48:57.820 --> 49:02.840
Stelle, an der die Hardware angesteuert werden soll, dass man da sagt,

49:03.040 --> 49:05.420
oh, das ist jetzt viel zu hoch.

49:05.600 --> 49:06.460
Dann wirft man Exception.

49:07.060 --> 49:11.620
Der Benutzer kriegt dann wieder in seiner Eingabemaske, also der

49:11.620 --> 49:14.680
Programmcode, der die Eingabemaske im Prinzip steuert, fängt diese

49:14.680 --> 49:17.780
Exception und zeigt das dem Benutzer zum Beispiel als rotes Feld an

49:17.780 --> 49:20.300
und sagt, das ist ungültig, die Eingabe geht so nicht.

49:20.560 --> 49:23.380
Und das Programm macht einfach an der Stelle weiter, wo es davor auch

49:23.380 --> 49:25.200
war und erwartet eine neue Eingabe.

49:25.620 --> 49:27.160
Wir konnten das reparieren in dem Augenblick.

49:27.280 --> 49:33.080
Wir konnten sagen, es ist zwar etwas Unerwartetes passiert, aber die

49:33.080 --> 49:36.040
Hardwaresteuerung kann damit nicht umgehen und weiß nicht, was sie tun

49:36.040 --> 49:36.320
soll.

49:36.460 --> 49:37.640
Sie erkennt nur, dass da was falsch ist.

49:37.900 --> 49:41.940
Aber die Eingabemaske, die kann jetzt ja die Situation retten und das

49:41.940 --> 49:44.020
Programm muss nicht komplett abstürzen an der Stelle.

49:44.480 --> 49:47.020
Wenn Exception dazu dient, dass das Programm an der Stelle tatsächlich

49:47.020 --> 49:50.780
komplett abstürzt, weil einfach gar nichts mehr möglich ist, die

49:50.780 --> 49:52.360
Situation nicht mehr gerettet werden kann.

49:53.300 --> 49:54.920
Exceptions sind nicht abschaltbar.

49:55.520 --> 49:57.000
Das ist ein ganz wichtiger Unterschied.

49:58.180 --> 50:01.240
Von der Syntax her sehen die beiden Dinge einfach so aus wie links,

50:01.380 --> 50:03.880
dass man Cert B Größe gleich 0 prüft.

50:04.180 --> 50:09.360
Rechts ein bisschen mehr Code zu schreiben, fb kleiner 0, row Illegal

50:09.360 --> 50:10.220
Argument Exception.

50:11.180 --> 50:13.160
Diese Exception kann abgefangen werden von dem Benutzer.

50:13.260 --> 50:16.920
Das heißt, der Benutzer dieser Methode weiß dann, oh Illegal Argument

50:16.920 --> 50:18.280
Exception ist wohl mein Fehler.

50:18.980 --> 50:21.620
Also sage ich dem Benutzer, in der Eingabemaske soll was anderes

50:21.620 --> 50:21.940
geben.

50:23.420 --> 50:27.440
Das hier wirft in der Realität tatsächlich auch eine Exception.

50:28.560 --> 50:32.620
Exceptions sind ebenfalls Exceptions implementiert, aber sie sollten

50:32.620 --> 50:33.800
Sie eigentlich niemals fangen.

50:35.100 --> 50:39.620
Wenn Sie jemals versuchen, eine Exception zu fangen, dann haben Sie

50:39.620 --> 50:42.020
wahrscheinlich im falschen Augenblick überhaupt eine Exception

50:42.020 --> 50:42.520
geworfen.

50:42.780 --> 50:46.720
Weil wie gesagt, Exceptions werden dafür benutzt, wenn man es nicht

50:46.720 --> 50:49.000
mehr reparieren kann und wenn es auch keinen Sinn mehr macht, das

50:49.000 --> 50:52.500
Ganze zu fangen und zu versuchen, noch irgendwas zu reparieren.

50:53.940 --> 50:56.820
Man macht Sinn, eine Illegal Argument Exception zu werfen und man

50:56.820 --> 50:58.900
macht Sinn, sich auf korrekte Eingaben zu verlassen.

50:59.620 --> 51:08.180
Es ist teilweise eine Entscheidung, die man vielleicht in Einzelfällen

51:08.180 --> 51:10.480
treffen muss, in individuellen Fällen.

51:10.600 --> 51:13.520
Es ist nicht immer so ganz klar zu sagen, dann ist immer das richtig,

51:13.740 --> 51:14.620
dann ist immer jenes richtig.

51:14.620 --> 51:20.040
Im Allgemeinen gilt, dass Sie sich niemals auf das verlassen sollten,

51:20.180 --> 51:22.140
was ein anderer Programmierer gemacht hat.

51:23.620 --> 51:27.360
Also wenn Sie eine Schnittstelle schreiben, eine Bibliothek schreiben,

51:27.460 --> 51:30.860
die jemand anderes in seinem Programm benutzen soll, dürfen Sie sich

51:30.860 --> 51:33.860
eigentlich nie darauf verlassen, dass er schon das richtig machen

51:33.860 --> 51:34.140
wird.

51:34.560 --> 51:36.180
Das wäre relativ fatal.

51:37.180 --> 51:41.840
Bei Ihrem eigenen Code, da wäre es vielleicht sinnvoller zu

51:41.840 --> 51:45.420
überprüfen, ob die Methode richtig aufgerufen wird, zum Beispiel eben

51:45.420 --> 51:46.100
ein Assertion.

51:46.940 --> 51:51.600
Gänzlich darauf verlassen würde ich mich vielleicht nie so recht, wenn

51:51.600 --> 51:52.820
es sehr performancekritisch ist.

51:52.880 --> 51:54.820
Aber dann kann man eben auch wieder Assertions nutzen, die Assertions

51:54.820 --> 51:57.460
ausschalten und dann kostet es ja auch nichts mehr an der Stelle.

51:58.100 --> 52:01.460
Aber im Allgemeinen gilt, die große Grenze ist eigentlich, jemand

52:01.460 --> 52:03.880
anderes ruft meine Methode auf, also prüfe ich das.

52:04.280 --> 52:05.980
Das gilt nicht nur für Methodenaufrufe.

52:06.100 --> 52:08.560
Also Methodenaufrufe ist eine Möglichkeit, wie in meinen Code

52:08.560 --> 52:09.420
reingesprungen wird.

52:09.420 --> 52:11.920
Die andere Möglichkeit ist ein Programmaufruf.

52:11.980 --> 52:14.120
Ich habe ein ganzes Programm geschrieben und rufe das Programm auf der

52:14.120 --> 52:14.900
Kommandozeile auf.

52:14.980 --> 52:17.840
Auch da muss natürlich die Eingabe geprüft werden.

52:20.140 --> 52:22.240
Mit den Folien bin ich soweit durch?

