it-swarm.com.de

Warum scheitern automatisierte Tests in meinem Unternehmen immer wieder?

Wir haben mehrmals versucht, automatisierte Entwicklertests in meinem Unternehmen einzuführen. Unser QS-Team verwendet Selenium, um UI-Tests zu automatisieren, aber ich wollte immer Unit-Tests und Integrationstests einführen. In der Vergangenheit waren jedes Mal, wenn wir es versuchten, alle für die ersten ein oder zwei Monate aufgeregt. Dann, einige Monate später, hören die Leute einfach auf, es zu tun.

Einige Beobachtungen und Fragen:

  1. Funktioniert das automatisierte Testen tatsächlich? Die meisten meiner Kollegen, die früher in anderen Unternehmen gearbeitet haben, haben versucht, eine automatisierte Teststrategie umzusetzen. Ich habe noch kein echtes Softwareunternehmen gesehen, das es tatsächlich verwendet und nicht nur darüber spricht. So viele Entwickler sehen automatisiertes Testen als etwas an, das theoretisch großartig ist, aber in der Realität nicht funktioniert. Unser Geschäftsteam würde es lieben, wenn Entwickler dies auch zu einem Preis von 30% mehr Zeit tun würden (zumindest sagen sie dies). Aber Entwickler sind Skeptiker.

  2. Niemand weiß wirklich, wie man automatisierte Tests richtig durchführt. Ja, wir haben alle die Beispiele für Unit-Tests im Internet gelesen, aber sie für ein großes Projekt zu verwenden, ist etwas ganz anderes. Der Hauptschuldige ist das Verspotten/Stubben der Datenbank oder alles andere, was nicht trivial ist. Am Ende verbringst du mehr Zeit damit, dich zu verspotten, als tatsächliche Tests zu schreiben. Wenn es dann länger dauert, Tests als Code zu schreiben, geben Sie auf.

  3. Gibt es etwas Gutes? beispiele von Unit-Tests/Systemintegrationstests, die in komplexen datenzentrierten Webanwendungen verwendet werden? Irgendwelche Open Source Projekte? Unsere Anwendung ist datenzentriert, verfügt aber auch über eine Vielzahl von Domänenlogiken. Ich habe den Repository-Ansatz irgendwann ausprobiert und fand ihn für Unit-Tests ziemlich gut, aber er ging zu Lasten der einfachen Optimierung des Datenzugriffs und fügte eine weitere Komplexitätsebene hinzu.

Wir haben ein großes Projekt von 20 erfahrenen Entwicklern. Dies scheint eine ideale Umgebung zu sein, um Unit-Tests/Integrationstests einzuführen.

Warum funktioniert es bei uns nicht? Wie haben Sie es in Ihrem Unternehmen zum Laufen gebracht?

182
Mag20

Der schwierigste Teil beim Testen von Einheiten besteht darin, die Disziplin dazu zu bringen, zuerst/früh Tests zu schreiben. Die meisten Entwickler sind es gewohnt, nur in Code einzutauchen. Es verlangsamt auch den Entwicklungsprozess frühzeitig, wenn Sie herausfinden möchten, wie ein Test für den Code geschrieben wird. Wenn Sie jedoch besser testen können, beschleunigt sich dies. Und aufgrund der Schreibtests beginnt die anfängliche Qualität des Codes höher.

Versuchen Sie zu Beginn nur, Tests zu schreiben. Mach dir am Anfang nicht so viele Sorgen über das Verspotten/Stubben von Dingen. Halten Sie die Tests einfach. Tests sind Code und können/sollten überarbeitet werden. Wenn etwas in diesem Sinne schwer zu testen ist, könnte es auch das Design sein. TDD tendiert dazu, die meisten Designmuster zu verwenden (meiner Erfahrung nach insbesondere das Factory-Muster).

Stellen Sie sicher, dass die Tests sichtbar sind. Integrieren Sie sie in den Release-Prozess, fragen Sie während der Codeüberprüfung nach ihnen. Alle gefundenen Fehler sollten getestet werden. In diesen Dingen strahlt TDD.

Hier sind einige Ressourcen, die ich nützlich gefunden habe:

http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf

http://www.agitar.com/downloads/TheWayOfTestivus.pdf

Bearbeiten:

Eine Sache, die Sie beachten sollten, wenn Sie Tests schreiben. Sie versuchen nicht, etwas über die Implementierung des Codes anzugeben, sondern nur das Verhalten. Wenn Sie Code schreiben, testen Sie ihn ständig. Der Versuch, es mit Debug-Anweisungen usw. auszuführen. Das Schreiben von Tests formalisiert dies und liefert eine Aufzeichnung der Tests, die Sie haben. Auf diese Weise können Sie Ihre Funktionalität sicher überprüfen, ohne versehentlich einen Testfall zu überspringen, an den Sie sich in der Mitte des Entwicklungsprozesses erinnert haben.

90
Schleis

In vielerlei Hinsicht stimme ich Ihrem Team zu.

  1. Die meisten Unit-Tests sind im Wert fraglich. Da die überwiegende Mehrheit der Tests zu einfach zu sein scheint.

  2. Es ist viel schwieriger, guten testbaren Code zu schreiben, als nur Arbeitscode. Es gibt einen großen Prozentsatz der Entwicklergemeinde, der daran glaubt, dass es nur funktioniert, im Vergleich zur Code-/Designqualität an sich. Und ein noch größerer Prozentsatz, der nicht einmal weiß, was Qualitätscode ist.

  3. Das Schreiben des Unit-Test-Codes kann viel länger dauern als der eigentliche Code.

  4. Es liegt außerhalb der Möglichkeiten vieler Entwickler, herauszufinden, wie der kompliziertere Code angemessen getestet werden kann (dh das Material, an dem Sie wirklich interessiert sind).

  5. Die Wartung von Komponententests dauert zu lange. Kleine Änderungen können große Welligkeitseffekte haben. Das Hauptziel automatisierter Komponententests besteht darin, herauszufinden, ob Änderungen den Code beschädigt haben. In 99% der Fälle brechen jedoch die Tests und nicht der Code.

Bei all den oben genannten Problemen gibt es immer noch keinen besseren Weg, um Codeänderungen vorzunehmen und ein gewisses Maß an Sicherheit zu haben, dass etwas nicht unerwartet kaputt gegangen ist, als Ihre Tests zu automatisieren.

Einige der oben genannten Punkte können bis zu einem gewissen Grad gelindert werden, indem das Lehrbuch der Unit-Tests nicht befolgt wird.

Viele Arten von Designs/Anwendungen werden besser getestet, indem Tests auf Modul-/Paketebene automatisiert werden. Nach meiner Erfahrung sind die meisten Codierungsfehler nicht darauf zurückzuführen, dass der Code in einer Klasse falsch codiert wurde, sondern darauf, dass der Codierer nicht verstanden hat, wie seine Klasse mit anderen Klassen funktionieren sollte. Ich habe bei dieser Art von Tests viel für das Geld gesehen. Aber auch hier sind diese Tests schwieriger zu schreiben als Unit-Tests (Klassenstufen).

Es kommt wirklich darauf an, ob die Entwickler an den Prozess glauben oder nicht. Wenn sie dies tun, werden sie gute Komponententests schreiben, Fehler frühzeitig finden und Befürworter sein. Wenn sie dies nicht tun, sind ihre Komponententests im Großen und Ganzen nutzlos und finden keine Fehler. Ihre Theorie, dass Komponententests nutzlos sind, wird sich (in ihren Augen) als wahr erweisen.

Fazit ist, dass ich selbst seit mehr als ein paar Monaten nicht mehr gesehen habe, wie der Ansatz des automatisierten Komponententests funktioniert, aber die Idee des automatisierten Komponententests bleibt bestehen, obwohl wir selektiv entscheiden, was wirklich getestet werden muss. Dieser Ansatz hat tendenziell weit weniger Kritiker und wird von allen Entwicklern eher akzeptiert als nur von wenigen.

77
Dunk

Der Hauptschuldige ist das Verspotten/Stubben der Datenbank oder etwas nicht Einfaches.

Und da ist dein Problem.

Jeder macht gute Punkte darüber, wie Sie Unit-Tests in Ihre Umgebung integrieren können. Wie man Leute dazu zwingt, es genug zu tun, dass sie den praktischen Wert sehen und es "klebt". Aber wenn es sehr schmerzhaft ist und/oder keinen Nutzen bringt, bleibt es nicht hängen.

Das Auslöschen einer Datenbank sollte kinderleicht sein. Anstatt dass Ihre Schnittstelle zu einem DB-Backing wechselt, um die Ergebnisse bereitzustellen, fügen Sie ein einfaches fest codiertes Objekt ein. Wenn Sie das nicht können, hat Ihr Design/Ihre Architektur Probleme. Ihr Code geht davon aus, dass er in eine Datenbank geht, oder Sie haben nicht die Schnittstellenabstraktion, um ihn zu variieren.

Dies ist nicht nur ein Test-/Qualitätsproblem. Sobald Sie den DB-Anbieter wechseln oder stattdessen in die Cloud wechseln oder nicht verbundene mobile Apps unterstützen möchten, schlägt Ihr Design einfach fehl. Wenn Sie die einfachsten Flexibilitätsfälle nicht unterstützen können, können Sie sicherlich nicht die komplexeren Dinge unterstützen, die Ihr Unternehmen zwangsläufig benötigt.

34
Telastyn

Sie müssen mit etwas Kleinem beginnen, das einfach zu automatisieren und von hohem Wert ist. Ziehen Sie einige süße, niedrig hängende Früchte herunter, und Sie können den Prozess verkaufen. Zeigen Sie, wie es jemandem eine späte Nacht oder einen Wochenendanruf erspart hat. Dann können Sie von dort aus erweitern.

Um automatisierte Tests gut durchführen zu können, benötigen Sie jemanden, der eine Ressource und ein Evangelist ist und der sich von höheren Managements eingekauft hat.

Behandeln Sie Ihre automatisierte Testentwicklung wie jedes andere agile Projekt. Erstellen Sie regelmäßig abgeschlossene Tests.

Aus Kommentar hinzufügen: Das ist eher ein Managementproblem. Wird der Code als "erledigt" betrachtet, bevor er dokumentiert wird? Bevor es eingecheckt wird? Bevor es Unit-Tests beinhaltet und besteht?

Wie Sie dies angehen, hängt wirklich von Ihrer Rolle ab. Bist du ein Peer? Wenn ja, zeigen Sie anderen, wie sie Ihren Code leichter wiederverwenden und warten können. Bist du ein Lead? Wählen Sie Ihren Programmierer mit den meisten Codeproblemen aus und helfen Sie ihm, Tests hinzuzufügen, um diese Probleme zu vermeiden. Bist du ein Chef? Legen Sie als Standard fest, dass "der Code erst erstellt wird, wenn die Komponententests abgeschlossen sind.

21
Skip Huffman

Befolgen Sie diese Grundregeln. Tests:

  1. muss regelmäßig laufen! Sie können Tests für jeden Build, vor/nach jedem Check-in oder nur jeden Morgen ausführen. Automatisch ausgelöst ist der manuellen Auslösung vorzuziehen . Theoretisch kann jeder im Team dafür verantwortlich sein, dass Tests durchgeführt werden. Wenn dies nicht automatisiert ist, geschieht dies wahrscheinlich nicht oft genug! Und wenn Sie Ihre Tests nicht oft genug ausführen, finden beide die Fehler zu spät, was zu vielen fehlerhaften Tests führt, was zu Punkt 2 führt:

  2. Sie werden immer noch nur erfolgreich sein, wenn diese Tests, die jetzt regelmäßig ausgeführt werden, nicht im Weg stehen . Womit wir Tests meinen:

    ein. Es darf nicht zu lange dauern, bis (subjektiv) der Wert erreicht ist, den sie bieten! Machen Sie Ihre Tests blitzschnell. Lassen Sie nicht zu, dass Leute Tests einchecken, die Ihre Zeit verschwenden, um sie laufen zu lassen!

    b. darf nicht unzuverlässig sein. Vermeiden Sie nach Möglichkeit Multithread-Tests. Wenden Sie technische Verfahren auf Ihre Tests an, genau wie auf Ihren anderen Code: insbesondere - Code überprüfen Sie Ihre Tests!

    c. darf nicht schwieriger zu reparieren und zu warten sein als der tatsächlich getestete Code. Ihre Codierungsgeschwindigkeit wird wirklich schlecht, wenn Sie bei einer winzigen Änderung Ihrer Codebasis um eine Zeile 10 verschiedene Tests korrigieren müssen.

Und schließlich Regel Nummer 3. Tests dürfen nicht nur keinen negativen Wert liefern, wie in Regel 2, sie müssen auch einen positiven Wert liefern. Tests ...

  1. muss tatsächlich Ihnen etwas sagen, das Sie interessiert , wenn sie versagen! (Bitte keine Tests mit obskuren Fehlermeldungen oder nur lächerlichen Beschwerden wie "Sie haben vergessen, den Test auf einem Windows 2008-Computer auszuführen"!).

Ein beliebter Weg, um Regel 3 zu verletzen, besteht darin, das Falsche zu testen . Dies liegt manchmal daran, dass ein Test zu groß oder zu unscharf ist. In der Regel wird jedoch nicht getestet, was einem Kunden wichtig ist, und es werden irrelevante Implementierungsdetails getestet. (Aber manchmal macht das Testen von Implementierungsdetails auch einen effizienten Test - IMO braucht es nur Übung, um zu entscheiden, welche.)

Fazit: Diese Grundregeln weisen Sie in die allgemeine Richtung einer nachhaltigen Testdisziplin, nach der Sie sich verzweifelt sehnen. Fragen Sie sich beim Testen, ob dieser Test wirklich nachhaltig und wartbar ist. Merken:

  • wenn Tests nicht nachhaltig sind, werden sie nicht mehr verwendet und werden dadurch zu unnötigem Aufwand
  • wenn Tests nicht nachhaltig sind, hören Sie auf, Tests durchzuführen, und Ihr Team kann nicht mehr besser testen! Und zum Schluss:

Testen ist eigentlich schwer. Sie sollten damit rechnen, dass die Tests Ihres Teams im Grunde genommen schlecht werden, wenn Sie anfangen, Tests zu schreiben . Lass dich nicht entmutigen. Do alte Tests wegwerfen, wenn Sie bemerken, dass sie saugen und nicht nachhaltig sind.

15

1. Funktioniert es wirklich?

Ja, wenn es richtig gemacht wird. Der Punkt ist, dass Tester ihre automatisierten Skripte anpassen und erweitern müssen, nachdem Ingenieure neue Funktionen implementiert haben.

2. Niemand ist wirklich erfahren oder weiß, wie man automatisierte Tests richtig durchführt.

Holen Sie sich einen Berater (jemand, der weiß, wie es richtig gemacht wird). Oder investieren Sie mehr Zeit. Die Alternative besteht darin, ein größeres Testteam zu haben, das die gleichen Tests manuell durchführt (was fehleranfällig ist).

3. Wir haben ein großes Projekt mit 20 erfahrenen Entwicklern, die daran arbeiten. Es sollte also eine großartige Umgebung sein, um Unit-Tests/Integrationstests einzuführen. Warum funktioniert es bei uns nicht? Wie haben Sie es in Ihrem Unternehmen zum Laufen gebracht?

Ich würde sie nicht "gute erfahrene Entwickler" nennen, wenn sie sich weigern, Unit-Tests durchzuführen. Es gibt viele großartige Artikel über die positiven Vorteile des Testens (sowohl Unit- als auch Integrationstests), und am Ende läuft es auf wie viel ein Fehler Ihr Unternehmen kostet . Zum Beispiel arbeite ich in einem Unternehmen, in dem es auf Qualität ankommt, daher sind Unit- und Integrationstests unvermeidlich. Sie können leicht viele Artikel finden, die besagen, dass nur Unit-Tests die Anzahl der Fehler um 30% reduzieren! (Eigentlich liegt es im Bereich von 20-90%, im Durchschnitt bei 30%, aber es ist immer noch viel.)

Damit es in Ihrem Unternehmen funktioniert, stellen Sie entweder einen Berater ein oder weisen Sie diese Aufgabe einem leitenden Ingenieur zu (es wird eine Weile dauern, bis er sie erledigt hat). Und dann zwingen Sie alle, sich an die Regeln zu halten.

12
BЈовић

Eine Sache, die ich in den obigen Antworten nicht klar angesprochen habe, ist, dass Unit-Tests im Wesentlichen ein öffentliches Gut und private Kosten sind. Ich habe einen Blog-Beitrag darüber geschrieben hier .

Es kommt darauf an, dass eine Testsuite dem Team oder einem einzelnen Entwickler zugute kommt, während der Test geschrieben wird kostet denjenigen, der es tut, die meiste Zeit.

Kurz gesagt, es sei denn, das Schreiben des Tests wird irgendwie erzwungen - und die obigen Antworten listen eine Reihe verschiedener Möglichkeiten auf, dies zu tun - gibt es keinen Grund für eine einzelner Entwickler, um dies zu tun.

In einem Unternehmen, bei dem ich gearbeitet habe, war das Schreiben von Komponententests ein erforderlicher Bestandteil der Bereitstellung einer Funktion. Neuer Code wurde nur akzeptiert, wenn ein Komponententest Teil des Commits oder der neuen Funktion war. Für jede "Aufgabe", die einem Entwickler gegeben wurde, gab es kurze Codeüberprüfungen. Es kann sich lohnen, eine ähnliche Richtlinie an Ihrem Arbeitsplatz umzusetzen.

11
Marco

Dies sind viele Gründe, warum die Einführung automatisierter Tests fehlschlagen könnte. Ich denke, es läuft darauf hinaus, dass Programmierer dazu neigen, ihre Codierungsgewohnheiten nicht zu ändern, und nicht in der Lage sind, Unit-Tests zu akzeptieren.

Viele Leute, die mit automatisierten Tests beginnen möchten, versuchen, sie für eine vorhandene Codebasis einzuführen. Sie werden versuchen, Integrationstests zu schreiben, die viele Funktionen der vorhandenen Anwendung gleichzeitig testen. Solche Integrationstests sind bekanntermaßen zu schwierig und zu teuer für die Wartung. Hinweis: Führen Sie automatisierte Tests für eine neue Codebasis ein.

Unit-Tests sind gute Tests, die automatisiert werden müssen. Alles oben Genannte (Integrationstests, Komponententests, Systemtests) kann ebenfalls automatisch getestet werden. Das Kosten-Nutzen-Verhältnis nimmt jedoch schnell ab, je mehr Funktionen gleichzeitig getestet werden. Dieser negative Effekt wird verstärkt, wenn Sie solche Tests auf schlecht getesteten Funktionen aufbauen. Hinweis: Führen Sie automatisierte Tests auf Unit-Test-Ebene ein und erstellen Sie automatisierte Integrationstests auf einer soliden Grundlage von Unit-Tests .

Von den oben genannten Punkten hängt ein Großteil des Erfolgs automatisierter Tests davon ab, wie effektiv die Komponententests sind. Sie haben effektive Unit-Tests, wenn Sie sich mit Unit-Tests produktiv fühlen. Wenn Menschen mit Unit-Tests beginnen, neigen sie dazu, ihren vorhandenen Code und ihre Codierungsgewohnheiten in Unit-Tests nachzurüsten. Ironischerweise ist dies der schwierigste Weg, Unit-Tests zu lernen. Für Unit-Tests müssen Sie auch die Art und Weise ändern, wie Sie codieren (z. B. die SOLID-Prinzipien anwenden). Die meisten Programmierer hören bald auf, Komponententests zu schreiben, weil sie der Meinung sind, dass die Lernkurve zu steil ist, und es schwierig finden, Komponententests um einen nicht so testbaren Code zu wickeln. Hinweis: Lernen Sie Unit-Tests von Grund auf mit neuem Code und gehen Sie mit der Tatsache um, dass Sie Ihre Codierungsgewohnheiten ändern müssen.

Es gibt viele andere Faktoren, aber ich fand, dass es für die meisten Programmierer schwierig ist, ihre Art des Codes zu ändern. Code, der ohne Test geschrieben wurde, sieht einfach anders aus. Wenn Sie Ihren Code nicht in ein testbares Design einbinden können, werden Sie höchstwahrscheinlich keine effektiven Komponententests schreiben. Dies zerstört den Boden für effektive automatisierte Tests.

Ich habe das selbst erlebt und bin jetzt glücklich, in einem Unternehmen zu arbeiten, das erfolgreich automatisierte Tests eingeführt hat. Ich könnte viel mehr über die anderen Faktoren schreiben, aber ich denke, dass Codierungsgewohnheiten und Unit-Tests die wichtigsten sind. Zum Glück gibt es andere, die mehr Erfahrung als ich haben und Bücher mit ihrem Know-how füllen. Eines dieser Bücher ist Brownfield Application Development in .NET , was ich wirklich empfehlen kann, da Sie den Microsoft-Technologie-Stack verwenden.

10
Theo Lenndorff

Es ist interessant, dass das Geschäft mehr Pro-Tests als Entwickler bietet! Für mich scheint Ihre größte Herausforderung darin zu bestehen, den Widerstand Ihrer Entwickler gegen Veränderungen zu überwinden. Sie müssen ihr Verständnis ihrer Arbeit neu definieren, um Unit-Tests einzuschließen.

Nichts kann Ihnen mehr helfen als frühe Erfolge bei Unit-Tests, um Ihren Entwicklern dabei zu helfen, ihren Widerstand gegen das Schreiben dieser Tests zu überwinden. Wenn Sie sie dazu drängen, etwas Neues zu tun, stellen Sie sicher, dass Sie zuerst auf etwas drängen, das eine fast garantierte Belohnung bietet.

@ SkipHuffman hat das angesprochen, aber ich werde es direkt sagen. Einige Dinge eignen sich viel besser für automatisierte Tests als andere. Für den ersten Durchgang würde ich [~ # ~] nicht [~ # ~] die Datenbank oder die Benutzeroberfläche testen. Eingaben aus einer Datenbank können äußerst schwierig einzurichten und abzubauen sein. UI-Ausgabetests werden in der Regel schnell durch Änderungen des Erscheinungsbilds unterbrochen, die für Ihre Tests völlig irrelevant sind.

Was ich "Middleware" nennen würde, ist perfekt für Unit-Tests. Code mit klar definierten Eingabe- und Ausgabebedingungen. Wenn Sie dem Prinzip DRY (Wiederholen Sie sich nicht)) folgen, haben Sie einige kleine Klassen oder Funktionen geschrieben, um wiederkehrende Probleme zu lösen, die für Ihre Anwendung einzigartig sind.

Unit-Tests sind ein großartiges Tool, um das Risiko einer Änderung vorhandener interner Komponenten zu begrenzen. Schreiben Sie Komponententests, bevor Sie eine interne Komponente ändern, die lange Zeit funktioniert hat. Diese Tests belegen, dass die aktuell funktionierende Funktionalität erhalten bleibt. Wenn Sie Ihre Änderung vorgenommen haben und alle Komponententests bestanden haben, wissen Sie, dass Sie nichts "Downstream" gebrochen haben. Wenn Sie ein nachgeschaltetes Problem finden, fügen Sie einen Komponententest hinzu!

Ron Heifitz würde sagen um "Konflikte in den Werten anzugehen, die Menschen vertreten, oder um die Kluft zwischen den Werten, für die Menschen stehen, und der Realität, mit der sie konfrontiert sind, zu verringern. Adaptive Arbeit erfordert eine Änderung von Werten, Überzeugungen oder Verhaltensweisen . " Nachdem Sie den menschlichen Widerstand gegen Veränderungen überwunden haben, können Sie gegebenenfalls in schwierigere Testbereiche verzweigen.

8
GlenPeterson

Eine Sache beim automatisierten Testen ist, dass Sie Code schreiben müssen, um testbar zu sein. Dies ist an und für sich keine schlechte Sache (in der Tat ist es gut, weil es viele Praktiken abschreckt, die in der Regel vermieden werden sollten), aber wenn Sie versuchen, Unit-Tests auf vorhandenen Code anzuwenden, ist dies wahrscheinlich nicht der Fall wurde auf prüfbare Weise geschrieben.

Dinge wie Singletons, statische Methoden, Register, Service Locators usw. führen Abhängigkeiten ein, die sehr schwer zu verspotten sind. Verstöße gegen das Demeter-Gesetz bedeuten, dass zu viele Teile Ihrer Codebasis zu viel darüber wissen, wie andere Teile Ihrer Codebasis funktionieren, was zu weiteren versteckten Abhängigkeiten führt, die möglicherweise nur schwer zu lösen sind. All diese Dinge machen es schwierig, ein Modul vom Rest der Codebasis zu isolieren. Wenn Sie Ihre Module nicht isoliert testen können, verlieren Unit-Tests viel an Wert. Wenn ein Test fehlschlägt, liegt dies an einem Fehler in der zu testenden Einheit oder an einem Fehler in einer ihrer Abhängigkeiten oder daran, dass die Daten, die über eine abhängige Datenquelle abgerufen werden, nicht den Erwartungen des Testschreibers entsprechen ? Wenn Sie Abhängigkeiten nicht durch Mocks ersetzen können, ist dies möglich.

Die meisten Codebasen, die ich gesehen habe und die nicht für Unit-Tests erstellt wurden, sind von Natur aus nicht testbar, da sich Codierer eher darauf konzentrieren, dass der Code so funktioniert, wie sie es erwarten, anstatt die Arbeit zu erledigen, die erforderlich ist, um die Kopplung locker zu halten und Abhängigkeiten explizit zu halten . Code, der für Unit-Tests geschrieben wurde, sieht in der Regel ganz anders aus.

Viele Leute gehen beim Testen von Einheiten naiv vor, wenn sie zum ersten Mal damit anfangen. Sie denken, sie können einfach eine Menge Tests für eine vorhandene Codebasis schreiben und alles wird gut, aber es funktioniert nie so die oben genannten Probleme. Sie stellen fest, dass sie in Unit-Tests übermäßig viele Einstellungen vornehmen müssen, damit sie überhaupt ausgeführt werden können. Die Ergebnisse sind häufig fraglich, da Sie aufgrund der fehlenden Isolation im Code nicht feststellen können, was einen Testfehler verursacht hat. Sie neigen auch dazu, zu versuchen, "clevere" Tests zu schreiben, die einen sehr abstrakten Aspekt der Funktionsweise des Systems demonstrieren. Dies schlägt tendenziell fehl, da ein "cleverer" Komponententest eine potenzielle Fehlerquelle für sich ist. Ist der Test aufgrund eines Fehlers im getesteten Modul oder aufgrund eines Fehlers im Test fehlgeschlagen? Ein Test sollte so einfach sein, dass es offensichtlich keine Möglichkeit gibt, dass sich ein Fehler darin versteckt. Tatsächlich sind die besten Tests selten länger als 2 Zeilen, wobei die erste Zeile das zu testende Gerät anweist, etwas zu tun, und die zweite behauptet, dass das, was es getan hat, das war, was erwartet wurde.

Wenn Ihr Team es ernst meint, Unit-Tests durchzuführen, ist es unklug, mit einem vorhandenen Projekt zu beginnen. Die bestehenden Projekte Ihres Teams sind wahrscheinlich ohne größere Umgestaltung nicht testbar. Sie sollten ein neues Projekt als Grundlage für das Erlernen von Unit-Tests verwenden, da Sie einen sauberen Plan haben, mit dem Sie arbeiten können. Sie können die neue Codebasis so gestalten, dass die Abhängigkeitsinjektion gegenüber Singletons, Registern und anderen solchen versteckten Abhängigkeiten bevorzugt wird. Sie können sie so schreiben, dass sie von Schnittstellen anstelle von Implementierungen usw. abhängt. Sie können (und sollten) die Tests auch neben dem zu testenden Code schreiben, da das anschließende Schreiben der Tests zu Komponententests führt, die sicherstellen, dass das getestete Modul das tut, was Sie für beabsichtigt halten, und nicht diejenigen, die es testen was die Spezifikationen sagen, sollte es tun.

Sobald Sie ein gewisses Vertrauen in Unit-Tests gewonnen haben, wird Ihr Team wahrscheinlich beginnen, die Fehler in seinem vorhandenen Code zu erkennen, die Hindernisse für Unit-Tests darstellen werden. In diesem Fall können Sie mit der Überarbeitung des vorhandenen Codes beginnen, um ihn testbarer zu machen. Seien Sie nicht ehrgeizig und versuchen Sie, dies alles auf einmal zu tun, oder versuchen Sie, ein System, das funktioniert, durch ein völlig neues zu ersetzen. Beginnen Sie einfach damit, die Teile der Codebasis zu finden, die leicht getestet werden können (diejenigen, die keine haben) Abhängigkeiten oder wo die Abhängigkeiten offensichtlich sind) und schreiben Sie Tests für diese. Ich weiß, dass ich sagte, dass das Schreiben eines Tests neben Code dem Schreiben von Tests nachzuziehen ist, aber selbst ein später geschriebener Test hat immer noch Wert als Ausgangspunkt. Schreiben Sie die Tests so, als ob Sie nichts darüber wissen, wie die Klasse funktioniert, außer was die Spezifikationen vorschreiben. Wenn Sie die Tests ausführen und Fehler erhalten, sind entweder die Spezifikationen oder die Implementierung falsch. Überprüfen Sie beide, um festzustellen, was falsch ist, und aktualisieren Sie entweder den Test oder den Code entsprechend.

Sobald Sie die tief hängenden Früchte gepflückt haben, beginnt Ihre eigentliche Arbeit. Sie müssen die versteckten Abhängigkeiten in Ihrer Codebasis finden und einzeln korrigieren. Seien Sie an dieser Stelle nicht zu ehrgeizig, sondern bleiben Sie bei einem Modul oder sogar nur einem einzigen Problem in einem Modul, bis die Hindernisse für das Testen behoben sind und Sie mit dem nächsten Schritt fortfahren können.

TL: DR: Die meisten Leute denken, dass das Testen einfach ist und Sie Tests problemlos in vorhandenen Code nachrüsten können. Beide Annahmen sind falsch. Wenn Sie ein Projekt starten, um Unit-Tests für Ihre Projekte unter Berücksichtigung dieser beiden Fakten durchzuführen, ist die Wahrscheinlichkeit höher, dass Sie Erfolg haben.

7
GordonM
  • Gibt es in Ihrem Unternehmen jemanden mit umfassender Erfahrung im Bereich automatisierter Tests?

Wenn nicht, werden automatisierte Testinitiativen wahrscheinlich fehlschlagen. Automatisiertes Testen ist eine Fähigkeit, wie viele andere Fähigkeiten in der Programmierung, und wenn Sie niemanden mit Erfahrung darin haben, ist es nicht leicht zu sagen, ob ein automatisierter Test ein guter automatisierter Test mit echtem Wert ist oder eine schlechte, die zufällig fehlschlägt/häufige Updates erfordert/keinen interessanten Code ausübt.

  • Hat das jemand Führungskraft? Können sie Veränderungen fordern?

Wenn niemand zuhört, spielt es keine Rolle, ob der Test nicht gut ist. (Beachten Sie, dass die Führungskraft nicht formalisiert werden muss. Ein Team zu haben, das sich interessiert, ist auch gut.)

  • Entwickeln Sie Tools und Prozesse, um automatisierte Tests einfacher zu implementieren und in den Entwicklungszyklus zu integrieren?

Entwickler sind faul. Sie müssen die Dinge, die sie tun sollen, einfach und die Dinge, die sie nicht tun sollen, schwieriger machen. Sie sollten sicherstellen, dass die Testbibliotheken die Ausführung der mit dem Einrichten und Herunterfahren von Tests verbundenen Aufgaben, insbesondere der umgebungsbezogenen Einrichtung, wie Testdatenbanken oder dergleichen, vereinfachen. (Das Verspotten der Datenbank wird in einigen dieser Kommentare erörtert, sollte jedoch mit Vorsicht verwendet werden. Eine echte Datenbank sollte leicht zu starten sein und es Ihnen ermöglichen, das Zusammenspiel von Komponenten und Prozesslebenszyklen zu testen, was häufig wichtiger und effektiver ist als Unit-Tests ein einzelner Datenzugriff.)

Sie sollten auch sicherstellen, dass Ihre IDEs eine gute Möglichkeit haben, die Testsuite zu starten. Sie sollten die Testsuite häufig ausführen, damit die Leute bemerken, wenn sie fehlschlägt, anstatt sie im Elend verweilen zu lassen. Entwickler reagieren auch gut auf Feedback, z. Ein automatisiertes Integrationssystem, das seine Änderungen zurücksetzt, wenn ein Test abgebrochen wurde. Oder besser positives Feedback: Ein automatisiertes Integrationssystem, das Fehler auffängt und Sie davor bewahrt, Dinge zu beschädigen.

4
user2348

Erstens, wenn Ihre Entwickler den Wert Ihrer Tests nicht sehen, liegt dies wahrscheinlich daran, dass Ihre Tests nicht wertvoll sind, nicht daran, dass Ihre Entwickler blind für ihren Wert oder für den Wert von Tests im Allgemeinen sind. Unter seinen Evangelisten besteht die Tendenz zu glauben, dass testgetriebene Entwicklung nicht scheitern kann, sondern nur von faulen, faulen Entwicklern gescheitert werden kann. Ich denke, das ist falsch und kontraproduktiv.

Als ich in die testgetriebene Entwicklung eingeführt wurde, bedeutete dies effektiv, einen Test zu schreiben, um zu überprüfen, ob eine Methode, die niemals versagt, niemals versagt. Was zunächst schön ist, weil man einen schönen grünen Scheck und ein Erfolgserlebnis bekommt. Später, nachdem Sie den Code überarbeitet haben, haben Sie Dutzende von wütenden roten Xes, von denen keines mehr aussagt als dass sich der Code geändert hat, dass die Tests nicht mehr gültig sind und dass Sie viel Zeit damit verschwendet haben, sie zu schreiben.

Das wollen Sie vermeiden.

Seitdem habe ich einen anderen Ansatz für Tests gewählt. Anstelle eines Schnittstellenimplementierungspaars habe ich eine Schnittstelle, Implementierung, Test Triple . Die Schnittstelle gibt das Verhalten an, die Implementierung führt das Verhalten aus, der Test überprüft das Verhalten.

Ich nehme an, es scheint offensichtlich, aber für mich unterscheidet es zwischen dem Code, den Sie nachweisen müssen, dass er wie angegeben funktioniert, und dem Code, den Sie so viel oder so wenig testen können, wie Sie für angemessen halten. Der Code, den Sie nachweisen müssen, ist die Schnittstelle, die Sie nach außen anbieten. Der Rest ist allein Ihr Anliegen.

In diesem Fall würde ich die Entwickler fragen, ob sie eine natürliche Unterteilung im Code sehen, wo diese Art von Test angemessen wäre. Gibt es eine Schnittstelle, die Team A implementiert und Team B verwendet? In diesem Fall liegt es im Interesse von Team B, sicherzustellen, dass sich die Schnittstelle wie erwartet verhält. Bitten Sie Team B, einen Test dafür zu schreiben, und fordern Sie Team A auf, sicherzustellen, dass die Implementierung dem Test entspricht. oder, wenn dies nicht der Fall ist und absichtlich nicht, die unerwartete Änderung mit dem anderen Team zu besprechen, damit es sich darauf vorbereiten kann.

Ich denke, dies würde den Wert des Tests veranschaulichen. Es ist kein Selbstzweck, trotz schöner grüner Karos. Es besteht die Möglichkeit, das Versprechen eines Entwicklers gegenüber einem anderen explizit zu machen und sicherzustellen, dass das Versprechen zur Zufriedenheit beider eingehalten wird.

4
drew

Ich denke, Sie müssen möglicherweise das lange Spiel spielen. Eine Sache, die Sie tun können, um eine gewisse Akzeptanz zu erreichen, ist zu versuchen, die nächste Funktion, die Sie schreiben, ausführlich zu testen und dann die Anzahl der Fehler im Laufe der Zeit zu verfolgen. Sie sollten hoffentlich feststellen, dass die Hauptfehler frühzeitig erkannt werden (insbesondere wenn Sie dies mit Test-Driven Design koppeln) und die Anzahl der Regressionen sehr gering sein sollte. Vergleichen Sie nach einem Zeitraum von beispielsweise 1 Jahr die Statistiken mit nicht auf Einheiten getesteten Funktionen ähnlicher Komplexität. Wenn Sie nachweisen können, dass die Anzahl neuer Fehler und Regressionen erheblich geringer ist, haben Sie eine finanzielle Begründung dafür geliefert, und es wird für das Produktteam schwieriger, diese zu ignorieren.

Ich hatte eine Situation, in der ich TDD und Unit-Tests für eine wichtige Funktion verwenden konnte. Nach dem Ende der Entwicklungsphase wurde in über 5 Jahren kein einziger Fehler gemeldet. Als eine neue - und riskante - Verbesserung angefordert wurde, konnte ich sie implementieren und alle Regressionen in den Komponententests erfassen.

2
the_mandrill

Das Hinzufügen vieler Komponententests zu einem großen bereits vorhandenen Projekt ist harte Arbeit. Wenn Sie bereits ein gutes Verspottungs-Framework gefunden haben, das für Sie funktioniert, sollten Sie das schwierigste Problem gelöst haben.

Ich schlage vor, Tests hinzuzufügen, während Sie Funktionen hinzufügen/Fehler beheben. Das Beheben von Fehlern ist am einfachsten. Schreiben Sie einen Test, der aufgrund Ihres Fehlers fehlschlägt, und beheben Sie den Fehler. Gleichzeitig werden Sie wahrscheinlich einige einfachere Tests schreiben, die bestehen. Natürlich möchten Sie dafür wirklich einen kleinen und leicht zu testenden Code verwenden.

Sobald sich die Leute daran gewöhnt haben, Tests für die einfacheren Dinge zu schreiben, sollten Sie hoffentlich feststellen, dass sie ihren Code schreiben, um testbarer zu sein.

Ich würde auch empfehlen, dass Sie die Codeabdeckung Ihrer Tests messen (ich habe cobertura für Java in der Vergangenheit) verwendet. Sie möchten einige kontinuierliche haben Integrationsserver, der die Tests ausführt und die Metriken regelmäßig erstellt (jeden Tag, jedes Einchecken). Wenn Ihre Entwicklerkollegen daran interessiert sind, möchten sie, dass die Abdeckung im Laufe der Zeit zunimmt, und sie können die klaffenden Abdeckungslöcher in einigen sehen von dir

2
brain

Ich bin der festen Überzeugung, dass der Wert von Unit-Tests von vielen Teams aufgrund mehrerer Faktoren, von denen viele bereits in den Antworten hervorgehoben wurden, weitgehend unterschätzt wird.

Oft stehen Entwickler unter dem Druck, "Dinge zu erledigen". Der Nachweis, dass ein Codeblock funktioniert, ist daher ein ausreichender Beweis für den Kunden. Dies gilt fast immer für Beratungsunternehmen und menschengesteuerte Qualitätssicherung: Wenn der Kunde keine Unit-Tests benötigt und eine ausreichende Live-Demo betrachtet, ist der Kunde völlig gescheitert, da er die Genehmigung für Code unterzeichnen wird, der Fehler verbergen könnte.

Oft sind Entwickler frustriert. Programmierer zu sein ist ein harter Job: Eine Aufgabe zu erledigen und zur nächsten zu gehen ist befriedigend, also möchte sich jeder beeilen und fertig werden. Bis sie von einem Bus mit einem großen Fehler getroffen werden, der Monate nach der ursprünglichen Qualitätssicherung auftritt. In diesem Szenario ist die automatisierte und kontinuierliche Qualitätssicherung eher das Problem des Managements als der Entwickler (sie werden immer noch für ihre Arbeit bezahlt, möglicherweise für Überstunden).

Es gibt jedoch eine Ausnahme

Ich bin der festen Überzeugung, dass die Akzeptanz des automatisierten Testmodells von der "Menschlichkeit" der durchgeführten Tests abhängt. Wenn Sie ein Webmodul mit einem Front-End testen, ist es trotz Tools wie Selen wahrscheinlicher, dass Sie das Formular selbst ausfüllen, das Ergebnis sehen und an Determinismus glauben. Sie werden vergessen, Tests später erneut auszuführen, oder Sie sind einfach zu faul, um alte Tests erneut durchzuführen. Aus diesem Grund werden Fehler manchmal später entdeckt. Um dies zu nutzen, haben sich eine starke Modularisierung des Codes und strenge Regeln zum "Ändern des alten Codes" in einem Bankumfeld als akzeptabel erwiesen (in meiner persönlichen Berufserfahrung).

Wenn der Entwickler für die Entwicklung eines hochautomatisierten Datenmoduls mit hohem Datenvolumen verantwortlich ist, wird er mit größerer Wahrscheinlichkeit gründliche Komponententests schreiben und diese an die Teststapel senden. Dies liegt daran, dass das Befüllen einer großen XML-Nutzlast mit Daten, die aus einer externen Datenquelle konvertiert wurden (verspottet oder nicht), keine Aufgabe für Menschen ist. Einige Testentwickler werden schließlich ein winziges und lustiges Frontend für diese spezielle Art von Tests erstellen. Als ich an meiner Masterarbeit arbeitete, arbeitete ich an einem Protokollierungsbus, der mehr als 6000 Syslog-Nachrichten pro Sekunde verarbeitete, und ich musste Paketverlust und -beschädigung messen: Ich schrieb natürlich Unit- und Stresstests für fast alle Komponenten, insbesondere den Syslog-Parser.

Um Entwickler anfälliger für Unit-Tests zu machen

Ich glaube, sie müssen dazu gezwungen werden. Wenn Sie ein intelligenter Kunde sind, müssen Ihre Berater bei jeder Qualitätssicherung die vollständige Testsuite ausführen. Wenn Sie ein guter Teamleiter sind, können Sie einem intelligenten Entwickler die folgende Aufgabe zuweisen: Erstellen Sie eine Plattform für innere Tests. Das hat nichts mit Antipatter der Plattform für innere Effekte zu tun, sondern besteht aus einer Reihe von Hilfsklassen, Datenbank-Mocks, Konfigurationen, Parsern, Konvertern und Schweizer Taschenmessern, mit denen Entwickler in kürzester Zeit Tests erstellen können.

Aktuelle Testplattformen wie NUnit sind universell einsetzbar und ermöglichen es Ihnen, allgemeine Aussagen zu überprüfen. Durch die korrekte Verwendung von Abhängigkeitsinjektion und projektspezifischen Fabriken können Entwickler weniger Code für Tests schreiben und zufriedener sein. Ich hatte noch keine Gelegenheit, dies an einem vollständigen Projekt zu experimentieren. Ich kann kein reales Feedback geben.

Automatisiertes Testen ist wie Softwareentwicklung. Leider sind die Personen, die Sie zum Testen einstellen, ursprünglich dazu gedacht, Testfälle, Pläne, Strategien zu schreiben, den Überprüfungsprozess zu verfolgen, Fehler manuell zu testen und zu protokollieren.

Sobald sie automatisierte Testverantwortlichkeiten erhalten, beinhaltet dies einen gewissen Umfang an Softwareentwicklung. Der Haken dabei ist, dass automatisierte Tests, unabhängig davon, welche Tools Sie verwenden (und um Himmels willen, argumentieren Sie diesen Punkt nicht), täglich gewartet und aktualisiert werden müssen. Wenn Entwickler Code ändern,

  • sie müssen sicherstellen, dass die Tests weiterhin ausgeführt werden.
  • Sie müssen sicherstellen, dass Tests nicht entfernt werden, da sie nicht ausgeführt wurden
  • ihre Testmetriken müssen zeigen, was Sie beim letzten Build und bei diesem Build ausgeführt haben. Um sicherzustellen, dass sich Ihre Anzahl an Testfällen nicht verringert.
  • testfälle müssen genau wie die Entwicklung überprüft werden, um sicherzustellen, dass die Leute nicht durcheinander kommen. Sie teilen 1 Test in 2, nur um die Zahlen zu erhöhen (manchmal werden Tests ausgelagert, daher ist dieses Tracking wichtig).
  • viel mehr "gesunde" Kommunikation zwischen Entwickler und Test ist wichtig
  • behalten non-functional Tests trennen sich und erwarten nicht, dass sie täglich ausgeführt werden. Es braucht Zeit, um diese auf dem neuesten Stand zu halten, und gut. Aber nicht aufgeben, sicherstellen, dass sie gewartet werden.

Sie scheitern aus diesen Gründen

  • ihre Testingenieure sind manuelle Testingenieure ohne analytische Fähigkeiten. Sie kennen den Unterschied zwischen einer if und einer while Schleife nicht. Da offen gesagt kein Kurs automatisiertes Testen lehrt, lehren sie nur manuelles Testen.
  • ihre Testingenieure sind zu beschäftigt damit, Ihre Builds manuell zu testen und Fehler zu protokollieren, damit sie den Überblick über automatisierte Tests verlieren
  • ihre Testmanager kümmern sich nicht um Metriken aus automatisierten Tests, nur weil sie ungültige Daten anzeigen (wenn das Projekt beginnt), und sie legen in täglichen Stand-ups und Besprechungen keine Anstrengungen oder Prioritäten fest, um zu betonen, wie wichtig es ist, die Automatisierung zum Laufen zu bringen
  • sie automatisieren Tests für mobile Anwendungen, die eine sehr kurze Haltbarkeit haben. Wenn Sie schreiben, stabilisieren Sie die automatisierte Testsuite, und Ihre Anwendungsanforderungen ändern sich. Stattdessen sollten Sie sich auf das Testen Ihrer Webservices konzentrieren, auf denen Ihre Anwendung ausgeführt wird
  • sie verstehen nicht, dass das automatisierte Testteam denselben Meilenstein verfolgt: Entwicklungsteam, Funktion vollständig, Code vollständig, Codesperre und Code einfrieren.
  • sie unterscheiden nicht zwischen manuellen und automatisierten Testern.
  • beide erhalten das gleiche Gehalt und berichten an denselben Manager. Idealerweise sollten sie sich an den Entwickler-Manager melden und ihre Gehälter sollten denen der Entwicklung entsprechen.
  • sie denken und glauben tatsächlich, dass junit nicht ausreicht, um automatisierte Tests zu entwickeln :).

Diese stammen aus meiner Erfahrung bei Unternehmen, die automatisierte Tests sehr ernst nehmen und verstehen, dass Entwickler als Ingenieure für automatisierte Tests wichtig sind. Und aus meiner Erfahrung, für Menschen zu arbeiten, die es nicht wissen, verstehen Sie den Unterschied, egal wie viel Sie ihnen erklären.

1
Siddharth