{"id":408,"date":"2015-05-23T10:10:03","date_gmt":"2015-05-23T08:10:03","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=408"},"modified":"2015-07-04T14:37:16","modified_gmt":"2015-07-04T12:37:16","slug":"testautomatisierung","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/testautomatisierung\/","title":{"rendered":"Testautomatisierung"},"content":{"rendered":"<p>Hallo Spa\u00df-Coder,<\/p>\n<p>habt ihr auch schon mal eine \u00c4nderung an eurem Code vorgenommen, alles gepr\u00fcft und hinterher stellte sich doch heraus, dass noch ein Fehler drin war? War dieser Fehler vielleicht in der Vergangenheit bereits einmal aufgetreten und ist nun wieder passiert? Oder seid ihr einmal in der Situation gewesen eine Anwendung zu pr\u00fcfen und habt euch dar\u00fcber ge\u00e4rgert, dass ihr bei jeder \u00c4nderung wieder von Vorne anfangen m\u00fcsst?<\/p>\n<p>In solchen F\u00e4llen hilft es uns, unsere Tests zu automatisieren.<\/p>\n<p>&nbsp;<\/p>\n<h2>Warum Testautomatisierung?<\/h2>\n<p>Stellt euch vor, wir sollen am unten abgebildeten System eine \u00c4nderung vornehmen. Das Verhalten soll sich also \u00e4ndern, wenn an dem 4. gr\u00fcnen Drehregler der 5. Reihe von rechts gedreht wird. Wo liegt nun das Problem?<\/p>\n<p><a href=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/MixingDesk.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-410\" src=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/MixingDesk.jpg\" alt=\"MixingDesk\" width=\"800\" height=\"533\" srcset=\"https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/MixingDesk.jpg 800w, https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/MixingDesk-300x200.jpg 300w, https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/MixingDesk-272x182.jpg 272w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>Nun, wir m\u00fcssen nun im Grunde jede Kombination der Drehregler pr\u00fcfen. Unser ge\u00e4nderter Drehregler ganz links, Mittelstellung und ganz rechts pr\u00fcft zun\u00e4chst, ob unsere gerade implementierte \u00c4nderung das gew\u00fcnschte Verhalten aufweist. Aber wie stellen wir sicher, das unser ge\u00e4nderter Drehregler auch dann noch funktioniert, wenn wir den schwarzen Drehregler hinten rechts nach ganz links drehen? Oder der zweite Schalter in der vorderen ersten Reihe gedr\u00fcckt ist&#8230;oder nicht gedr\u00fcckt ist?<\/p>\n<p>Wer von euch hat Lust, all diese Kombinationen manuell zu \u00fcberpr\u00fcfen? Keiner? Das \u00fcberrascht uns nicht.<\/p>\n<p>Schaut euch mal das Bild an. Nun denkt an euer aktuelles Software-Projekt. Ist euer Software-Projekt wesentlich weniger Komplex als das abgebildete System? Habt ihr nicht auch ganz verschiedene Kombinationsm\u00f6glichkeiten von Einstellungen, bei denen ihr nicht absch\u00e4tzen k\u00f6nne, welche Auswirkungen sie auf den Rest eures Systems haben?<\/p>\n<p>Wenn wir also ein solches System haben, bei dem wir bei jeder \u00c4nderung immer wieder unz\u00e4hlige Kombinationen testen und pr\u00fcfen m\u00fcssen, wie w\u00fcrden wir uns w\u00fcnschen, wie das abl\u00e4uft?<\/p>\n<p>Vielleicht so:<\/p>\n<p><a href=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/RollerCoaster.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-411\" src=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/RollerCoaster.jpg\" alt=\"RollerCoaster\" width=\"800\" height=\"600\" srcset=\"https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/RollerCoaster.jpg 800w, https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/RollerCoaster-300x225.jpg 300w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>Nach einer \u00c4nderung an unserem System dr\u00fccken wir auf einen Knopf und ab geht die Wilde Fahrt. Das System l\u00e4uft los und testet sich selbst und das immer und immer wieder. Sobald wir auf den Knopf dr\u00fccken, testet sich das System und wir erhalten unmittelbar eine R\u00fcckmeldung dar\u00fcber, ob das System noch funktioniert oder nicht.<\/p>\n<p>Noch besser w\u00e4re f\u00fcr unsere Software-Systeme, dass sie sich automatisch pr\u00fcfen, wir also nicht einmal mehr auf den Knopf dr\u00fccken m\u00fcssen. Aber das ist f\u00fcr uns Software-Entwickler ja die leichteste \u00dcbung. Bei dem abgebildeten System ist das Vorgehen vielleicht nicht die beste aller Ideen \ud83d\ude09<\/p>\n<p>&nbsp;<\/p>\n<p>Machen wir noch ein anderes Beispiel. Nehmen wir an, wir haben das unten abgebildete System f\u00fcr einen unserer Kunden entwickelt. Es funktioniert seit ein paar Monaten. Durch eine neue Attraktion in der N\u00e4he hat sich aber das Verkehrsaufkommen ge\u00e4ndert und in einer der von unserem System gesteuerten Zufahrtsstra\u00dfen kommt es seit ein paar Tagen immer wieder zu Staus. Unser Kunde m\u00f6chte nun, dass wir die Steuerung so \u00e4ndern, dass die Staus nicht mehr vorkommen.<\/p>\n<p><a href=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLight-.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-414\" src=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLight-.jpg\" alt=\"ComplexTrafficLight\" width=\"800\" height=\"966\" srcset=\"https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLight-.jpg 800w, https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLight--248x300.jpg 248w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>Was machen wir also? Wir ermitteln die Ursache f\u00fcr die Staus und ver\u00e4ndern das Verhalten unseres Systems so, dass diese in Zukunft nicht mehr vorkommen. Aber was nun? K\u00f6nnen wir mit Gewissheit sagen, dass unsere \u00c4nderung nicht Staus an anderen Stellen des Systems verursacht? K\u00f6nnen wir sicherstellen, dass das System als Ganzes noch funktioniert?<\/p>\n<p>Der Kunde m\u00f6chte schnell eine L\u00f6sung haben. Aber wenn wir unsere \u00c4nderung durchgef\u00fchrt haben und das neue Verhalten an unsere Kunden ausliefern, darf es auf gar keinen Fall so enden:<\/p>\n<div id=\"attachment_412\" style=\"width: 810px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLightNight.jpg\"><img aria-describedby=\"caption-attachment-412\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-412\" src=\"http:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLightNight.jpg\" alt=\"Pierre Vivant's sculpture, Traffic Light Tree in the Docklands, London\" width=\"800\" height=\"640\" srcset=\"https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLightNight.jpg 800w, https:\/\/invidit.de\/blog\/wp-content\/uploads\/2015\/05\/ComplexTrafficLightNight-300x240.jpg 300w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><p id=\"caption-attachment-412\" class=\"wp-caption-text\">Pierre Vivant&#8217;s sculpture, Traffic Light Tree in the Docklands, London<\/p><\/div>\n<p>Wir m\u00fcssen sicherstellen, dass das System weiterhin genauso funktioniert wie vorher, aber das ge\u00e4nderte Verhalten f\u00fcr die eine Zufahrtsstra\u00dfe aufweist. Wir wollen aber &#8211; genauso wie im obigen Beispiel &#8211; nicht alle Kombinationen des Systems manuell pr\u00fcfen. Auch w\u00e4re es nicht im Sinne unseres Kunden, wenn wir die \u00c4nderung erst einmal wochenlang einem manuellen Test unterziehen, bevor er die \u00c4nderung bekommt. Bis dahin werden viele Autofahrer ver\u00e4rgert sein, vielleicht wird es sogar Verkehrsunf\u00e4lle geben. Es ist also wichtig, dass unsere \u00c4nderung schnell zum Kunden kommt. So stellen wir den Kunden zufrieden und erh\u00f6hen damit auch die Wirtschaftlichkeit unserer Leistung.<\/p>\n<p>Mit unseren Software-Systemen ist das genauso. Der Kunde m\u00f6chte ein ge\u00e4ndertes Verhalten. Wir implementieren es und m\u00fcssen sicherstellen, dass<\/p>\n<ol>\n<li>unsere \u00c4nderung so funktioniert, wie der Kunde sich das vorstellt<\/li>\n<li>unsere \u00c4nderung an einem Teil des Systems nicht andere Teile negativ beeinflusst<\/li>\n<li>wir unsere \u00c4nderung wirtschaftlich profitabel umsetzen <strong>und<\/strong> pr\u00fcfen<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h2>Arten der Testautomatisierung<\/h2>\n<p>Es gibt verschiedene Arten von Tests, auf die wir in folgenden Artikeln noch weiter eingehen werden hier zun\u00e4chst eine kurze \u00dcbersicht, was euch zum Thema noch erwartet:<\/p>\n<ul>\n<li><strong>UI-Test<\/strong><br \/>\nIm UI-Test wird unsere Anwendung auf Basis der <strong>Benutzer-Oberfl\u00e4che<\/strong>, also aus Sicht des Anwenders, gepr\u00fcft. UI-Tests stellen die h\u00f6chste Ebene des Tests dar. Es wird die Anwendung als ganzes getestet, nicht einzelne Teile daraus. Einen UI-Test f\u00fchrt auch der Anwender aus, wenn er \u00fcberpr\u00fcft, ob unsere erstellte Anwendung seinen Anforderungen gen\u00fcgt..<\/li>\n<li><strong>Regressionstest<\/strong><br \/>\nIm Regressionstest pr\u00fcfen wir, dass es in einer neuen <strong>Version<\/strong> unserer Software keine unerw\u00fcnschten \u00c4nderungen gibt. Dazu werden die Ergebnisse der Software <strong>vor<\/strong> unserer \u00c4nderung mit den Ergebnissen der Software <strong>nach<\/strong> der \u00c4nderung verglichen. Diese Tests pr\u00fcfen typischerweise nicht die Oberfl\u00e4che, sondern die in der darunterliegenden Schicht befindlichen Funktionen und Services. Der Begriff wird oft auch als als Synonym f\u00fcr &#8222;wiederholbare automatisierte Tests&#8220; verwendet.<\/li>\n<li><strong>Integrationtest<\/strong><br \/>\nIn einem Integrationstest pr\u00fcfen wir, ob mehrere<strong> Komponenten<\/strong> unseres Softwaresystems zusammenpassen. Ob also z.B. unsere Datenbankzugriffe auch dann noch funktionieren, wenn sie \u00fcber einen Service angesprochen werden, oder verschiedene Datenbankanfragen hintereinander das gleiche Ergebnis liefern, wie die einzeln getesteten Anfragen.<\/li>\n<li><strong>Unit-Test<br \/>\n<\/strong>Bei einem Unit-Test werden einzelne <strong>Komponenten <\/strong>unseres Softwaresystems gepr\u00fcft. Eine Einheit (engl. Unit) kann dabei eine Klasse oder eine Funktion sein.<\/li>\n<\/ul>\n<p>Diese Testarten bauen aufeinander auf. Von unten (Unit-Test) nach oben (UI-Test) pr\u00fcfen sie immer allgemeinere Teile unserer Anwendung. Unsere Klassen und Funktionen (Methoden) werden in einzelnen Unit-Tests gepr\u00fcft. Ein System vereint in aller Regel bereits mehrere Komponenten und kann somit nur in einem Integrationstest sinnvoll getestet werden. Das Zusammenspiel dieser Systeme wird dann durch unsere Regressionstests \u00fcberpr\u00fcft und ob das Ganze f\u00fcr den Anwender die gew\u00fcnschte Wirkung hat, pr\u00fcfen unsere UI-Tests.<\/p>\n<p>Alle Ebenen sind gleich wichtig, da sie aber aufeinander aufbauen, sollte beim Test mit den unteren Ebenen begonnen werden. Beim BDD &#8211; dem Behavior Driven Development &#8211; fangen wir in der Regel oben in der Kette an, aber darauf kommen wir zu einem sp\u00e4teren Zeitpunkt nochmal zu sprechen.<\/p>\n<p>&nbsp;<\/p>\n<h2>Was spricht f\u00fcr Testautomatisierung?<\/h2>\n<p>Zusammenfassend noch einmal kurz, was daf\u00fcr spricht, unsere Tests zu automatisieren.<\/p>\n<ul>\n<li>Wiederholbarkeit<\/li>\n<li>klare Erwartungen<\/li>\n<li>leicht \u00fcberpr\u00fcfbar<\/li>\n<li>schnelles Feedback<\/li>\n<li>Aufdecken unerw\u00fcnschter Side-Effects an der Software<\/li>\n<li>nachhaltige Wirtschaftlichkeit bei der Entwicklung<\/li>\n<\/ul>\n<p>Aus den oben genannten Beispielen sollten hervorgehen, warum wir diese Aspekte mit Testautomatisierung erreichen.<\/p>\n<p>&nbsp;<\/p>\n<h2>Was spricht gegen Testautomatisierung?<\/h2>\n<p>Wie bei allem gibt es auch bei der Testautomatisierung Nachteile. Es sind:<\/p>\n<ul>\n<li>Kosten<\/li>\n<li>Wartung des Test-Codes<\/li>\n<li>Know-How-Aufbau<\/li>\n<\/ul>\n<p>Wenn wir nun zus\u00e4tzlich zu unserem Produktionscode nun auch immer Tests schreiben, werden wir mehr Zeit brauchen, um ein neues Feature zu entwickeln. Es wird also teurer.<\/p>\n<p>Genauso sieht es aus, wenn wir das Verhalten unserer Software \u00e4ndern. Soll ein Fenster nun keinen roten Rahmen mehr haben, sondern einen blauen, unser Test aber auf einen blauen Rahmen pr\u00fcft, m\u00fcssen wir nicht nur die Farbe des Rahmens \u00e4ndern, sondern auch den Test, da der ja bisher auf einen roten Rahmen gepr\u00fcft hat. Auch hier wird das \u00c4ndern eines Verhaltens teurer, da wir nicht nur das Verhalten, sondern auch den Test-Code anpassen m\u00fcssen.<\/p>\n<p>Zum Schluss m\u00fcssen wir auch Know-How zum Thema Test-Automatisierung aufbauen. Wir m\u00fcssen und mit Werkzeugen besch\u00e4ftigen, f\u00fcr uns klar machen, wie wir damit arbeiten m\u00f6chten, Test-Methodiken lernen und entwickeln&#8230; auch das kostet Zeit.<\/p>\n<p>Unterm Strich kann man alle Nachteile auf einen Punkt reduzieren: Kosten. Wir sehen diese Kosten aber weniger als Kosten, sondern vielmehr als Investition. Wir investieren in Know-How und die Erstellung automatisierter Tests, um die oben aufgelisteten Vorteile erreichen zu k\u00f6nnen.<\/p>\n<p>&nbsp;<\/p>\n<h2>Unsere Erfahrung mit Testautomatisierung<\/h2>\n<p>Seit einigen Jahren setzen wir in unseren <a href=\"http:\/\/invidit.de\/blog\/1-1-3\/\">Pair-Programming<\/a>-Sessions auf Unit-Tests. Auch Integrationstests schreiben wir oft, vor allem, wenn wir Test-Driven (zuerst der Test, dann erst der Produktionscode) vorgehen (was wir nicht immer machen). Es ist einfach ein gutes Gef\u00fchl, wenn wir eine Klasse oder ein Modul refaktorisieren, dass wir sicher sein k\u00f6nnen, dass es hinterher auch noch genau das macht, was es soll. Oder wenn wir ein neues Feature hinzuf\u00fcgen, sicher sind, dass alle anderen Features noch funktionieren. Es gibt uns Sicherheit und macht uns mutiger, auch mal gr\u00f6\u00dfere \u00c4nderungen durchzuf\u00fchren.<\/p>\n<p>In unserem beruflichen Kontext arbeiten wir mit sehr komplexen Software-Systemen und vermissen dort an vielen Stellen eine durchg\u00e4ngige Test-Automatisierung. Hier erfahren wir am eigenen Leib was es bedeutet, Tests nicht zu automatisieren. Vor allem weil wir das (Fern-)Ziel eines Continuous-Delivery verfolgen ist es f\u00fcr uns unabdingbar, das Thema weiter voranzutreiben und so viele Tests wie m\u00f6glich zu automatisieren.<\/p>\n<p>&nbsp;<\/p>\n<p>Habt ihr nach dem Lesen des Artikels noch Fragen? Seid ihr mit einem Aspekt nicht einverstanden oder seht ihr weitere Vorteile \/ Nachteile bei der Testautomatisierung? Wir freuen uns \u00fcber euer Feedback in den Kommentaren und w\u00fcnschen euch viel Spa\u00df beim Ausprobieren.<\/p>\n<p>Eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p>Dieser Artikel basiert neben unseren Erfahrungen auf folgenden Quellen:<\/p>\n<ol style=\"list-style-type: lower-alpha;\">\n<li>http:\/\/de.wikipedia.org\/wiki\/Modultest<\/li>\n<li>http:\/\/de.wikipedia.org\/wiki\/Integrationstest<\/li>\n<li>http:\/\/de.wikipedia.org\/wiki\/Regressionstest<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Verwendete Bilder:<\/p>\n<p><span style=\"font-size: 8pt;\">Mischpult: <a href=\"https:\/\/www.flickr.com\/photos\/95213174@N08\/13296791174\/\">https:\/\/www.flickr.com\/photos\/95213174@N08\/13296791174\/<\/a><\/span><br \/>\n<span style=\"font-size: 8pt;\">Achterbahn: <a href=\"https:\/\/www.flickr.com\/photos\/buschap\/3960386389\">https:\/\/www.flickr.com\/photos\/buschap\/3960386389<\/a><\/span><br \/>\n<span style=\"font-size: 8pt;\"> Traffic Light Tree in the Docklands:\u00a0<a href=\"https:\/\/www.flickr.com\/photos\/46239552@N00\/4852958993\">https:\/\/www.flickr.com\/photos\/46239552@N00\/4852958993<\/a> <\/span><br \/>\n<span style=\"font-size: 8pt;\">Traffic Light Tree in the Docklands nachts:\u00a0<a href=\"https:\/\/www.flickr.com\/photos\/wwarby\/2460655511\/\">https:\/\/www.flickr.com\/photos\/wwarby\/2460655511\/<\/a> <\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df-Coder, habt ihr auch schon mal eine \u00c4nderung an eurem Code vorgenommen, alles gepr\u00fcft und hinterher stellte sich doch heraus, dass noch ein Fehler drin war? War dieser Fehler vielleicht in der Vergangenheit bereits einmal aufgetreten und ist nun wieder passiert? Oder seid ihr einmal in der Situation gewesen eine Anwendung zu pr\u00fcfen und [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":422,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[90],"tags":[70,76,69,77,75,32,71],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/408"}],"collection":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=408"}],"version-history":[{"count":5,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/408\/revisions"}],"predecessor-version":[{"id":444,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/408\/revisions\/444"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/422"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=408"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=408"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=408"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}