"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[756],{2632:function(e,n,t){t.d(n,{Z:function(){return l}});var a=t(7294),s=t(5444),r=t(7450);function l(e){var n=e.pages;return a.createElement("nav",{className:"bg-diit border-b border-gray-200 flex","aria-label":"Breadcrumb"},a.createElement("ol",{role:"list",className:"max-w-screen-xl w-full mx-auto px-4 flex space-x-4 sm:px-6 lg:px-8"},a.createElement("li",{className:"flex"},a.createElement("div",{className:"flex items-center"},a.createElement(s.Link,{to:"/",className:"text-white hover:text-blue-300"},a.createElement(r.tvw,{className:"flex-shrink-0 h-5 w-5","aria-hidden":"true"}),a.createElement("span",{className:"sr-only"},"Home")))),n.map((function(e){return a.createElement("li",{key:e.name,className:"flex"},a.createElement("div",{className:"flex items-center"},a.createElement("svg",{className:"flex-shrink-0 w-6 h-full text-white",viewBox:"0 0 24 44",preserveAspectRatio:"none",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},a.createElement("path",{d:"M.293 0l22 22-22 22h1.414l22-22-22-22H.293z"})),a.createElement(s.Link,{to:e.href,className:"ml-4 text-sm font-medium text-white hover:text-blue-300","aria-current":e.current?"page":void 0},e.name)))}))))}},7922:function(e,n,t){t.d(n,{Z:function(){return s}});var a=t(7294);function s(){return a.createElement("div",{dangerouslySetInnerHTML:{__html:'\n\n
\nprivate void Confirm(object input, string classification)\n{\n    if (input != null)\n    {\n        var inputType = input.GetType();\n        foreach (var pi in inputType.GetProperties())\n        {\n            var attribute = pi.GetCustomAttributes(false)\n                .Where(a => a is DatasetValidationAttribute)\n                .Cast()\n                .FirstOrDefault();\n            var classificationName = classification + "." + pi.Name;\n            if (string.IsNullOrEmpty(classification) == true)\n            {\n                classification = pi.Name;\n            }\n\n            var propertyValue = pi.GetValue(input);\n            if (propertyValue != null)\n            {\n                if (pi.PropertyType.IsClass && pi.PropertyType != typeof(String))\n                {\n                    if (typeof(IEnumerable).IsAssignableFrom(pi.PropertyType) == false)\n                    {\n                        Confirm(propertyValue, classification);\n                    }\n                    else\n                    {\n                        var index = 0;\n                        var enumerable = propertyValue as IEnumerable;\n                        if (enumerable != null)\n                        {\n                            foreach (var item in enumerable)\n                            {\n                                var itemType = item.GetType();\n                                if (itemType.IsClass && itemType != typeof(String))\n                                {\n                                    Confirm(item, classification+$"[{index}]");\n                                }\n                                else\n                                {\n                                    if (attribute != null && itemType == typeof(String))\n                                    {\n                                        StartConfirmation(attribute, classification + $"[{index}]",\n                                            item.ToString());\n                                    }\n                                }\n\n                                index++;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (attribute != null && pi.PropertyType == typeof(String))\n                    {\n                        StartConfirmation(attribute, classification, propertyValue.ToString());\n                    }\n                }\n            }\n        }\n    }\n}\n
\n \n \n'}})}},2854:function(e,n,t){t.d(n,{Z:function(){return s}});var a=t(7294);function s(){return a.createElement("div",{dangerouslySetInnerHTML:{__html:'\n\n
\npublic Benutzer SucheBenutzer(string suchtext)\n{\n    var benutzer = _controller.SucheBenutzer(suchtext);\n    if(benutzer == null)\n    {\n        throw new UserNotFoundException(suchtext);\n    }\n    return benutzer;\n}\n
\n\n\n'}})}},9381:function(e,n,t){t.d(n,{Z:function(){return s}});var a=t(7294);function s(){return a.createElement("div",{dangerouslySetInnerHTML:{__html:'\n\n
\npublic void GeneriereLebenslauf(int benutzerId)\n{\n    FindeBenutzer(benutzerId)\n        .OnSuccess(ErzeugeLebenslauf)\n        .OnError(LogErrorMessage);\n}\n
\n\n\n'}})}},7198:function(e,n,t){var a=t(7294),s=t(5444),r=t(1615),l=t(3375),i=t(5186);n.Z=function(e){var n=e.children;(0,s.useStaticQuery)("3649515864");return a.createElement(a.Fragment,null,a.createElement(i.q,{htmlAttributes:{lang:"de-DE"}}),a.createElement("div",{className:"relative h-full bg-gray-100 font-sans"},a.createElement(r.Z,null),a.createElement("main",null,n)),a.createElement(l.Z,null))}},4320:function(e,n,t){t.r(n),t.d(n,{default:function(){return c}});var a=t(7294),s=t(7198),r=t(6179),l=t(2632),i=(t(5444),t(2359));t(7922),t(9381),t(2854);function c(){return a.createElement(a.Fragment,null,a.createElement(s.Z,null,a.createElement(r.Z,{title:"Artikel: Test Driven Development (TDD)"}),a.createElement(l.Z,{pages:[{name:"Artikel",href:"/Artikel",current:!1},{name:"Test Driven Development (TDD)",href:"/Artikel/TestDrivenDevelopment",current:!0}]}),a.createElement("div",{className:"relative py-16 bg-white overflow-hidden max-w-3xl mx-auto mt-10 sm:rounded-lg"},a.createElement("div",{className:"hidden lg:block lg:absolute lg:inset-y-0 lg:h-full lg:w-full"},a.createElement("div",{className:"relative h-full text-lg max-w-prose mx-auto","aria-hidden":"true"},a.createElement("svg",{className:"absolute top-12 left-full transform translate-x-32",width:404,height:384,fill:"none",viewBox:"0 0 404 384"},a.createElement("defs",null,a.createElement("pattern",{id:"74b3fd99-0a6f-4271-bef2-e80eeafdf357",x:0,y:0,width:20,height:20,patternUnits:"userSpaceOnUse"},a.createElement("rect",{x:0,y:0,width:4,height:4,className:"text-gray-200",fill:"currentColor"}))),a.createElement("rect",{width:404,height:384,fill:"url(#74b3fd99-0a6f-4271-bef2-e80eeafdf357)"})),a.createElement("svg",{className:"absolute top-1/2 right-full transform -translate-y-1/2 -translate-x-32",width:404,height:384,fill:"none",viewBox:"0 0 404 384"},a.createElement("defs",null,a.createElement("pattern",{id:"f210dbf6-a58d-4871-961e-36d5016a0f49",x:0,y:0,width:20,height:20,patternUnits:"userSpaceOnUse"},a.createElement("rect",{x:0,y:0,width:4,height:4,className:"text-gray-200",fill:"currentColor"}))),a.createElement("rect",{width:404,height:384,fill:"url(#f210dbf6-a58d-4871-961e-36d5016a0f49)"})),a.createElement("svg",{className:"absolute bottom-12 left-full transform translate-x-32",width:404,height:384,fill:"none",viewBox:"0 0 404 384"},a.createElement("defs",null,a.createElement("pattern",{id:"d3eb07ae-5182-43e6-857d-35c643af9034",x:0,y:0,width:20,height:20,patternUnits:"userSpaceOnUse"},a.createElement("rect",{x:0,y:0,width:4,height:4,className:"text-gray-200",fill:"currentColor"}))),a.createElement("rect",{width:404,height:384,fill:"url(#d3eb07ae-5182-43e6-857d-35c643af9034)"})))),a.createElement("div",{className:"relative px-4 sm:px-6 lg:px-8"},a.createElement("div",{className:"text-lg max-w-prose mx-auto"},a.createElement("h1",null,a.createElement("span",{className:"block text-base text-center text-blue-500 font-semibold tracking-wide uppercase"},"Schneller, bessere Software entwickeln"),a.createElement("span",{className:"mt-2 block text-3xl text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl"},"Test Driven Development")),a.createElement("p",{className:"mt-8 text-xl text-gray-500 leading-8"},"Über Test-Driven-Design (TDD) wurde schon sehr viel geschrieben und dieser Artikel soll und kann keine Einführung in das Thema sein. Er soll vielmehr Entwickler dazu animieren, sich mit dem Thema auseinanderzusetzen. Ich beschreibe die Vorteile von TDD aus meiner persönlichen Entwicklungserfahrung und hoffe, dass es den einen oder anderen den entscheidenden Anstoß gibt, TDD einmal selbst auszuprobieren.")),a.createElement("div",{className:"mt-6 prose prose-blue prose-lg prose-quoteless text-gray-500 mx-auto"},a.createElement("h2",null,"Der TDD Grundzyklus"),a.createElement("p",null,"Statt gleich die gewünschten Klassen zu implementieren, fängt man mit einem Test an. Dieser schlägt natürlich fehl, da es ja noch keinen Code gibt, der die eigentlich zu testende Funktion umsetzt. Im nächsten Schritt implementiert man den Code solange, bis der Test grünes Licht gibt."),a.createElement("p",null,"An diesem Punkt hat man nun eine funktionierende Methode. Jetzt geht man hin und überlegt sich, wie man den Code noch ein bisschen schöner / sauberer machen kann. Anschließend prüft man den Test wieder. Diesen Zyklus wiederholt man solange, bis man zufrieden ist."),a.createElement("div",{className:"flex items-center justify-center text-sm"},a.createElement(i.S,{src:"../../images/TDD-Grundzyklus.png",formats:["auto","webp","avif"],alt:"Der TDD Grundzyklus",__imageData:t(3316)})),a.createElement("h2",null,"Arten von Tests"),a.createElement("p",null,"Ich halte die Einteilung von Tests in die folgenden Kategorien für sinnvoll und ausreichend:"),a.createElement("ul",null,a.createElement("li",null,a.createElement("span",{className:"font-bold"},"Unit Tests:")," Ein Unit Test testet")),a.createElement("p",null),a.createElement("h2",null,"Frühes Testen vs. Spätes Testen"),a.createElement("p",null,"In den meisten meiner Projekte wurde eher spät mit dem Testen angefangen, also kurz vor dem offiziellen Release. Einfache Unit- und Integration-Tests wurden zwar früher entwickelt, aber die richtigen End-to-End-Tests und Acceptance-Tests kamen erst ganz spät. Und dann passiert praktisch immer das Gleiche: die Tests fördern Probleme zutage, an die bislang keiner gedacht hat. Wenn es ganz schlecht läuft, entdeckt man grundsätzliche Design-Probleme, die nicht mal eben schnell behoben werden können, sondern einen beträchtlichen Teil an Neuentwicklung benötigt!"),a.createElement("p",null,"Jetzt können zwei Dinge passieren:"),a.createElement("ul",null,a.createElement("li",null,"Das Release wird verschoben und das Problem sauber behoben."),a.createElement("li",null,"Es wird ein Work-around gefunden, der das Problem kaschiert, so dass das Release trotzdem stattfinden kann. Es wird beschlossen, bei nächster Gelegenheit das Problem sauer zu beheben.")),a.createElement("p",null,"In der Regel wird sich für Letzteres entschieden. Ob das Design-Problem in der Folge behoben wird, ist fraglich. Falls es nicht behoben wird, geht man eine technische Schuld ein. Meistens dauert es nicht lange, bis man genau wegen dieser technischen Schuld eine andere Funktion nicht sauber umsetzen kann und für diese ebenfalls eine weitere technische Schuld eingehen muss. Je mehr dieser Schulden gemacht werden, desto schwieriger wird es, zukünftig Funktionen sauber umzusetzen."),a.createElement("p",null,"Durch TDD ist die Gefahr dieses Teufelskreises deutlich geringer. Im Idealfall baut man ganz früh schon End-to-End-Tests und Acceptance-Tests, damit grundsätzliche Probleme sofort sichtbar werden."),a.createElement("p",null,"Das Problem dabei ist: nach außen sieht es am Anfang so aus, als würde das Projekt keine Fortschritte machen, weil nichts Sichtbares vorgewiesen werden kann. Es muss so viel eingerichtet, konfiguriert, gemockt usw. werden, dass Projektverantwortliche leicht nervös werden. Selten wird erkannt, dass durch das frühe Lösen dieser Probleme hinten raus sehr viel Zeit gewonnen wird. Das wird von Projektverantwortlichen leider nicht immer so gesehen; im Gegenteil: aus Erfahrung wissen sie, dass es kurz vor dem Release immer zu Chaos und Verzögerung kommt und sie denken, wenn sie jetzt schon am Anfang keinen Fortschritt sehen, wie soll es erst kurz vor dem Release werden?"),a.createElement("p",null,"Frühes Testen dreht aber diesen Spieß um und reduziert das Chaos am Ende deutlich spürbar. Das folgende Schaubild soll das illustrieren:"),a.createElement(i.S,{src:"../../images/FruehTesten-SpaetTesten.png",formats:["auto","webp","avif"],alt:"Früh testen vs. Spät testen",__imageData:t(5895)}),a.createElement("p",null,"Ein weiterer häufig zu beobachtender Negativeffekt von spätem Testen ist: sobald man anfängt, einen Test zu entwickeln, stellt man fest, dass die Komponenten in der aktuell implementierten Form gar nicht testbar sind!"),a.createElement("p",null,"Es könnte zum Beispiel sein, dass die zu testenden Daten aufgrund des Zugriffslevel (protected / private) gar nicht zugreifbar sind. Das Design sieht es einfach nicht vor. Man sollte jetzt aber nicht die für den Test notwendigen private Properties einfach auf public umstellen, nur damit man testen kann. Bei einem solchen Fall merkt man, dass nicht von Anfang an ans Testen gedacht wurde. Hätte man TDD gemacht, wäre das sofort aufgefallen und man hätte gleich gemerkt, dass mit dem Design etwas nicht stimmt."),a.createElement("p",null,"Fortsetzung folgt..."))))))}},5895:function(e){e.exports=JSON.parse('{"layout":"constrained","backgroundColor":"#f8f8f8","images":{"fallback":{"src":"/static/e844241a5a8e0e8203f3947b94201683/2d23c/FruehTesten-SpaetTesten.png","srcSet":"/static/e844241a5a8e0e8203f3947b94201683/1de41/FruehTesten-SpaetTesten.png 275w,\\n/static/e844241a5a8e0e8203f3947b94201683/d88a5/FruehTesten-SpaetTesten.png 550w,\\n/static/e844241a5a8e0e8203f3947b94201683/2d23c/FruehTesten-SpaetTesten.png 1100w","sizes":"(min-width: 1100px) 1100px, 100vw"},"sources":[{"srcSet":"/static/e844241a5a8e0e8203f3947b94201683/c385f/FruehTesten-SpaetTesten.avif 275w,\\n/static/e844241a5a8e0e8203f3947b94201683/aa3a6/FruehTesten-SpaetTesten.avif 550w,\\n/static/e844241a5a8e0e8203f3947b94201683/be853/FruehTesten-SpaetTesten.avif 1100w","type":"image/avif","sizes":"(min-width: 1100px) 1100px, 100vw"},{"srcSet":"/static/e844241a5a8e0e8203f3947b94201683/afdee/FruehTesten-SpaetTesten.webp 275w,\\n/static/e844241a5a8e0e8203f3947b94201683/f3167/FruehTesten-SpaetTesten.webp 550w,\\n/static/e844241a5a8e0e8203f3947b94201683/38403/FruehTesten-SpaetTesten.webp 1100w","type":"image/webp","sizes":"(min-width: 1100px) 1100px, 100vw"}]},"width":1100,"height":650}')},3316:function(e){e.exports=JSON.parse('{"layout":"constrained","backgroundColor":"#f8f8f8","images":{"fallback":{"src":"/static/a422edc2aadbf7cfc47f5cc8c6bf0835/12d6b/TDD-Grundzyklus.png","srcSet":"/static/a422edc2aadbf7cfc47f5cc8c6bf0835/e1b03/TDD-Grundzyklus.png 125w,\\n/static/a422edc2aadbf7cfc47f5cc8c6bf0835/17734/TDD-Grundzyklus.png 250w,\\n/static/a422edc2aadbf7cfc47f5cc8c6bf0835/12d6b/TDD-Grundzyklus.png 500w","sizes":"(min-width: 500px) 500px, 100vw"},"sources":[{"srcSet":"/static/a422edc2aadbf7cfc47f5cc8c6bf0835/42f51/TDD-Grundzyklus.avif 125w,\\n/static/a422edc2aadbf7cfc47f5cc8c6bf0835/cbfed/TDD-Grundzyklus.avif 250w,\\n/static/a422edc2aadbf7cfc47f5cc8c6bf0835/1fdae/TDD-Grundzyklus.avif 500w","type":"image/avif","sizes":"(min-width: 500px) 500px, 100vw"},{"srcSet":"/static/a422edc2aadbf7cfc47f5cc8c6bf0835/46142/TDD-Grundzyklus.webp 125w,\\n/static/a422edc2aadbf7cfc47f5cc8c6bf0835/2cd09/TDD-Grundzyklus.webp 250w,\\n/static/a422edc2aadbf7cfc47f5cc8c6bf0835/f03ce/TDD-Grundzyklus.webp 500w","type":"image/webp","sizes":"(min-width: 500px) 500px, 100vw"}]},"width":500,"height":280}')}}]); //# sourceMappingURL=component---src-pages-artikel-test-driven-development-js-0c68288f8bb5bad517f5.js.map