Was können Sie tun, um die Qualität bestehender Integrations- und Unit-Tests zu verbessern, während Sie der neue Typ in einem Team sind?

21

Ein wiederkehrendes Thema, auf das ich in meiner Karriere gestoßen bin, ist, als neuer Entwickler in ein Team einzusteigen und schnell ein inhärentes Misstrauen gegenüber den vorhandenen Unit- und Integrationstestsuiten zu haben.

Während des Interviews werden Sie von der Geschäftsleitung darüber informiert, dass sie "Unit-Tests nachdrücklich unterstützen" und dies offen unterstützen. Sie tun es, aber alles an den Tests selbst ist einfach falsch. Wie die Tatsache, dass sie eine 100% ige Abdeckung beanspruchen, wenn es eine 100% ige Abdeckung für Integrationstests, aber weniger als 10% für wiederholbare Einheitentests gibt. Einige andere Probleme, die ich gefunden habe:

  1. Keine eindeutige Angabe zwischen einem Unit-Test und einem Integrationstest. Unit- und Integrationstests werden in derselben Klasse gemischt.

  2. Integrationstests, bei denen explizite Abhängigkeiten von sehr spezifischen dynamischen Daten in der Datenbank einer bestimmten Umgebung nicht deklariert wurden.

  3. Nicht-transaktionale Integrationstests, im Grunde genommen Tests, die sich die Mühe machen oder nicht, nach sich selbst aufzuräumen, und manchmal manuelles "Scrubbing" der Datenbank erfordern, um den Test wiederholbar zu machen.

  4. Kein Verspotten, und der Anwendungscode muss grundlegend überarbeitet werden, damit das Verspotten möglich ist. Mit anderen Worten: Entwerfen ohne zu prüfen.

  5. Keine eindeutigen Namenskonventionen, um schnell einen Testnamen anzeigen und ungefähr bestimmen zu können, welche Tests durchgeführt werden.

Das soll nicht heißen, dass ALLE Tests nutzlos oder schlecht sind, ein Großteil davon ist ziemlich gut und es lohnt sich, sie zu behalten, aber manchmal scheint es, als würde man nach Gold suchen. Ich würde es absichtlich vermeiden, Tests durchzuführen, nur weil ich Angst hatte, die Datenbank für meine Black-Box-Testfälle zu vermasseln.

Dies hat mir im Wesentlichen ein inhärentes Misstrauen gegenüber Unit- und Integrationstests gegeben, die ich nicht persönlich geschrieben oder in irgendeiner Weise überprüft habe. Wenn Sie auf einer bestimmten Ebene kein Vertrauen in die Qualität Ihrer Testsuite haben, bringt dies dem Team oder dem Projekt überhaupt keinen Wert.

Was machen Sie, wenn Sie sich in dieser Situation befinden? Was ist Ihrer Meinung nach der beste Angriffsplan, um so etwas in Angriff zu nehmen?

Sollten alle Tests in einem monumentalen Aufwand über Releases hinweg überarbeitet werden? Sollten Sie einfach auf die Idee verzichten, dass dieses Legacy-Projekt eine eintägige solide Einheitentestabdeckung haben könnte?

maple_shaft
quelle
6
Willkommen in der realen Welt, Kumpel.
tdammers
20
Sei froh, dass du Tests hast.
Joel Etherton
3
Warum arbeiten Sie für Unternehmen, die deutlich unter Ihrem Kompetenzniveau liegen?
TrojanName
3
@Brian, ich schätze den Ego-Strich, aber ohne mehr Leute, die so denken wie ich, werden sich diese Unternehmen niemals erheben. Dies ist das erste Mal, dass ich eine tatsächliche Machtposition einnehme, da ich ausnahmsweise eine bescheidene politische Bedeutung entwickelt habe. Ich habe hier eine echte Gelegenheit, Ressourcen zu lenken, um die Dinge zu verbessern. Ich habe noch keine Firma gefunden, die perfekt ist, ohne Arbeit zu benötigen. Es ist wie mit dem perfekten Ehemann oder der perfekten Ehefrau, sie kommen nicht einfach mit, eine Person, die gut genug ist, und dann ändern Sie sie in das, was Sie möchten;)
maple_shaft
1
Ich denke, wir könnten für dasselbe Team arbeiten. Jetzt wissen Sie (und ich), wie Sie bei unseren nächsten Interviews tatsächlich Fragen stellen. (Eigentlich hat meine Umgebung nicht annähernd 100% oder sogar 10% Integrationstestabdeckung [echte Komponententests? Das ist verrückte Rede!], Aber Sie haben alle anderen Punkte, mit denen ich zu tun habe, genau festgelegt.)
Anthony Pegram,

Antworten:

6

Zuallererst sollten Sie, wie andere Poster bereits geschrieben haben, froh sein, dass Unit- / Integrationstests verstanden (nicht auf technische Weise, ich meine, der Grund, warum es getan werden sollte, ist verstanden) und vom Management vorangetrieben werden.

Bevor Sie anfangen, alles zu tun, sollten Sie die Probleme dem Management darlegen, warum etwas getan werden sollte, und zwar sehr diplomatisch, damit sie nicht glauben, dass Sie der beste Programmierer der Welt sind (auch wenn Sie es sind! :-). Vielleicht werden sie Ihnen sagen, dass die Anwendung durch etwas völlig Neues ersetzt wird, und wenn ja, warum sich die Mühe machen. Und vielleicht werden sie erkennen, dass es nett wäre und die Testphase vor jeder Veröffentlichung beschleunigen. Und seien Sie diplomatisch mit Ihren Teamkollegen , es kann Millionen Gründe geben, warum es so ist, und es gibt einfach keinen Grund, einen Schuldigen zu suchen.

Eine bessere Idee wäre, zu versuchen, mit ihnen zu sprechen, damit sie an den Bemühungen teilnehmen können, und Sie haben weniger Chancen, als schlauer Esel aufzutreten. Es wäre mehr "wir" als "ich".

Setzen Sie nun Prioritäten für das, was Sie tun möchten. Priorisieren Sie die Aufgaben, immer in dem Wissen, dass Ihre aktuelle Projektaufgabe immer Ihre erste Priorität sein wird ... Was Ihr Testproblem betrifft, würde ich Folgendes in drei Phasen tun:

  1. Wie kann man zwischen Unit- und Integrationstests unterscheiden? Die folgenden Lösungen können zutreffen und sind nicht exklusiv:

    • Refaktorieren Sie den Namen der Testfallmethoden (nicht die Klassen, da das richtige Verhalten darin besteht, dass der Testfall denselben Namen wie die getestete Klasse hat).
    • Erstellen Sie zwei Anmerkungen, eine mit dem Namen "UnitTest" und eine mit dem Namen "IntegrationTest". Diese Anmerkungen können für Klassen und Methoden verwendet werden. Wenn eine gesamte Klasse aus Unit- oder Integrationstests besteht, können Sie die Klasse mit der richtigen Anmerkung markieren. Wenn nicht, können Sie jede Methode mit der richtigen Anmerkung markieren. Diese Anmerkungen können auch nützlich sein, um Fixtures vor dem Start der Tests dynamisch zu injizieren (Phase 3).
  2. Geben Sie für jeden Integrationstest an, welches "Dataset" zu Beginn jedes Tests in der Datenbank vorhanden sein soll und was am Ende entfernt werden soll (Beispiel: Tabelle X, benötigt einen Datensatz mit "id"). auf "1" setzen und "name" auf "foo" setzen, etc.). Beachten Sie, dass das, was Sie entfernen, größer / kleiner sein kann als das, was Sie zu Beginn haben, da der Code selbst Objekte zur Persistenzebene hinzufügen / daraus entfernen kann. Sie werden höchstwahrscheinlich schnell feststellen, dass mehrere dieser Testfälle denselben Datensatz oder einen Teil desselben Datensatzes benötigen.

  3. Die ersten beiden Phasen können relativ schnell durchgeführt werden ... im Vergleich zu den anderen. Nachdem Sie Ihr Dataset erstellt haben, verwenden Sie die Funktion zum Erstellen von Dataset-Fixtures für jeden Testfall, der dies benötigt. Aber das wird einige Zeit kosten ... Also können Sie eine machen, sehen, wie viel Zeit es kostet und abschätzen, wie viel Zeit Sie brauchen, um alles zu tun. Sie können diesen Test auch verwenden, um Ihren Kollegen zu demonstrieren, was Sie getan haben und warum das Leben so viel einfacher ist, wenn Sie keine Datenbank in einem bestimmten Status benötigen, um Tests durchzuführen.

Möglicherweise stellen Sie fest, dass Phase 1, 2 und 3 für eine einzelne Testklasse durchgeführt werden kann, wenn Sie Kollegen / Führungskräften schnell zeigen möchten, wie dies durchgeführt werden kann. Dies wäre auch nützlich, wie Péter Török schrieb, um Ihren Teamkollegen sofort den "guten Weg" zu zeigen, damit sie keinen schlechten Code mehr produzieren. Ich denke jedoch, dass der Rest der Phase 2, in der der gesamte Testdatensatz identifiziert wird, am besten in einem großen Schritt erledigt wird.

In Bezug auf die API / Technologie dahinter scheinen Sie das Thema zu kennen.

Hoffe das hat ein bisschen geholfen.

Hinweis: Für meinen Vorschlag gehe ich davon aus, dass Sie entweder in Java / C # codieren, wo ich weiß, dass Anmerkungen und AOP möglich sind. Ich bin sicher, dass dies auch in anderen Sprachen möglich ist, aber ich werde nicht über etwas schreiben, das ich nicht weiß.

Jalayn
quelle
1
Vielen Dank ... Ich habe überlegt, Anmerkungen als Bezeichnungen zu verwenden, um zu identifizieren, was ein Integrationstest und was ein Komponententest ist. Wissen Sie, ob es möglich ist, einen CI-Server wie CruiseControl so zu konfigurieren, dass bestimmte Tests basierend auf Anmerkungen ausgeschlossen werden? Vielleicht ist das eine andere Frage.
maple_shaft
Es tut mir leid, dass ich CruiseControl nicht kenne, daher weiß ich nichts darüber. Ich habe in der Surefire-Plugin-Konfiguration von Maven nachgesehen, nur um mich zu interessieren, und es scheint nicht möglich zu sein, aber es ist durchaus möglich, Tests basierend auf Namen zu überspringen.
Jalayn,
14

Sie können nicht alle Tests zusammen reparieren. Ich denke, Sie sollten sich auf die Verbesserung gegenüber der Überholung konzentrieren . Weder das Management noch die Entwickler werden sich auf eine Überholung einigen. Wenn Sie jedoch zeigen, dass es eine Möglichkeit gibt, Dinge zu verbessern, ohne das Projekt negativ zu beeinflussen, werden sie mit größerer Wahrscheinlichkeit zuhören.

Erstens können Sie vorhandenen Code nur dann „reparieren“ oder umgestalten, wenn Sie über eine qualitativ hochwertige Testabdeckung verfügen. Ich würde mich daher zunächst auf die Korrektur Ihrer Testinfrastruktur konzentrieren.

Machen Sie eine Liste der Dinge, die verbessert werden müssen, und versuchen Sie, sie zu priorisieren. Ich denke, dass die Fähigkeit, Tests unabhängig und einzeln durchzuführen (so dass sie sich nicht gegenseitig beeinflussen) und die Trennung von Unit- und Integrationstests einige der ersten Dinge sind, an denen gearbeitet werden muss. Sie müssen es Ihnen und anderen leicht machen, das Richtige zu tun.

Was den Anwendungscode anbelangt ... Sie können die Anwendungsarchitektur nicht vollständig überarbeiten, nur um sie besser auf Einheit testen zu können. Versuchen Sie stattdessen, beim Einfügen von neuem Code Prinzipien anzuwenden, die den Komponententest erleichtern (z. B. Abhängigkeitsinjektion). Sie mögen denken, dass dies nicht groß genug für eine Änderung ist, aber es ist erstaunlich, wie schnell sich Entwickler durchsetzen, wenn sie den Nutzen erkennen. Es muss nur jemanden geben, der eine Veränderung zum Besseren vornimmt.

Sprechen Sie mit Ihrem Team und fordern Sie es zum Buy-In auf. Eines der wichtigsten Dinge, die Sie tun können, ist das Befolgen der Pfadfinder-Regel und kleine Verbesserungen, um eine Klasse zu verlassen oder einen Test in einem besseren Zustand durchzuführen, als Sie ihn gefunden haben . Wenn das ganze Team diese Regel anwendet, wird es viel schneller besser.

Nach einer Weile werden Sie eine Menge Code haben, der guten Prinzipien und Bereichen der Anwendung folgt, die in einem schlechten Zustand sind. An diesem Punkt haben Sie einen Überblick über das, was gut ist, und das Team kann entscheiden, ob es von Vorteil ist, einen größeren Refaktor für das ältere Legacy-Material zu erstellen, oder es kann einfach so weiterleben, wie es ist.

c_maker
quelle
8
+1, und ich füge hinzu: "Fange an, indem du mit gutem Beispiel vorangehst." Niemand schätzt den Mann, der hereinkommt und sagt, dass Sie es falsch machen, aber wenn Sie Verbesserungen zeigen, werden sie eher mitmachen.
StevenV
2
+1 für die Pfadfinderregel ist es viel einfacher zu verwenden und zu verkaufen als jeder Überholungsansatz.
Matthieu M.
10

Ich muss zugeben, dass ich es als seltenes Geschenk ansehen würde, zu einem Projekt zu gelangen, bei dem bereits eine beträchtliche Anzahl von Unit- / Integrationstests durchgeführt wurde - ich hatte bisher noch nie dieses Glück in meinem Leben. Auch wenn nicht alle von ihnen so arbeiten, wie sie sollten, wird bereits viel Aufwand betrieben, und auch wenn das Team und das Management nicht immer die besten Praktiken befolgen, sind sie dennoch bereits der Sache verpflichtet, also Sie Sie müssen nicht lange darüber streiten, warum Komponententests es wert sind, geschrieben zu werden.

Die Tests, wie Sie sie beschreiben, können in der Tat einige Verbesserungen bringen. Aber Sie müssen mit Ihrem Ton vorsichtig sein, wenn Sie die Probleme mit Ihren Teamkollegen besprechen . Wenn Sie anfangen zu sagen "alles an den Tests selbst ist einfach falsch" , können Sie den Rest des Teams sehr schnell entfremden. Stattdessen sollten Sie sich darauf konzentrieren, den aktuellen Stand der Dinge zu verbessern, der - ich muss es wiederholen - nach meinen bisherigen Erfahrungen immer noch deutlich über dem Durchschnitt liegt.

IMO sollte Ihr erstes Ziel sein, das Team daran zu hindern, mehr schlechte Tests zu produzieren . Beginnen Sie also damit, Ihren Teamkollegen den Nutzen jeder einzelnen Verbesserung zu demonstrieren. Wenn sie den Nutzen einer bestimmten Technik erkennen - sei es, externe Abhängigkeiten zu beseitigen, den ursprünglichen Zustand nach jedem Test wiederherzustellen oder Einheits- und Integrationstests zu trennen - werden sie diese anwenden. Dies an sich wird die Gesamtqualität der Testbasis auf lange Sicht langsam aber sicher verbessern (wenn Sie jetzt 1000 schlechte Testfälle haben und das Team bis zum nächsten Jahr 1000 gute Tests erstellt, haben Sie das Verhältnis der schlechten Tests gesenkt von 100% bis 50%). Sobald dies sichergestellt ist, können Sie von Fall zu Fall entscheiden, ob vorhandene Tests überarbeitet werden sollen. Auch hier führen kleine Verbesserungen im Laufe der Zeit zu großen Änderungen.

Als Randnotiz, nach dem Tonfall Ihres Postens habe ich das Gefühl, dass Sie sich an einem Ort befinden, an dem ich es früher auch getan habe: Sie vertrauen nicht auf die Arbeit anderer, können keine Aufgaben an jemanden delegieren, aus Angst, dass ihre Arbeit nicht Ihren Anforderungen entspricht eigene Qualitätsstandards. Nach meiner Erfahrung ist dies kein guter Ort, da es auf lange Sicht leicht zu persönlichen Konflikten und Burnout kommen kann. Man kann nicht alles alleine machen, man muss mit dem Rest des Teams zusammenarbeiten. Sie können nur gemeinsam erfolgreich sein.

Péter Török
quelle
6

Arbeiten Sie auf Testunabhängigkeit hin. Wenn Test X die Testdatenbank so ändert, dass Test Y fehlschlägt, ändern Sie Test Y. In diesem kleinen Szenario sollte nicht darauf geachtet werden, dass X die Datenbank durcheinander gebracht hat, sondern dass Y unangemessene Abhängigkeiten aufweist. Entfernen Sie diese Abhängigkeiten (indem Sie die Datenbank löschen, den Test umstrukturieren oder die Datenbank in einen Zustand initialisieren, in dem Y bestanden wird), und jetzt haben Sie einen weiteren unabhängigen, funktionierenden Test. Das ist ein Fortschritt (wahrscheinlich wäre es nicht, X zu "reparieren", um die Datenbank nicht durcheinander zu bringen).

Seien Sie geduldig und respektvoll, so gut Sie können, mit den Leuten, mit denen Sie arbeiten, trotz der Unordnung, die sie verursacht haben. Höchstwahrscheinlich versuchen sie, das Richtige zu tun. Denken Sie daran und helfen Sie ihnen dabei.

Carl Manaster
quelle
2
Ich hätte erwähnen sollen, dass keiner der ursprünglichen Chaosschöpfer mehr hier ist. Sie hatten keine Lust, sich mit der technischen Verschuldung auseinanderzusetzen, die sie geschaffen hatten, und zogen weiter.
maple_shaft
4
@maple_shaft: Es ist gut, dass sie weg sind ... Sie können Dinge verbessern, ohne dass jemand das Gesicht verliert.
Kevin Cline
2

Das Gute daran, neu im Team zu sein, ist, dass man die Dinge "frisch" angeht. Das Schlimme kann sein, dass andere es schwer haben, Ihnen zu glauben.

Machen Sie keine Wäscheliste mit Dingen, die zu erledigen sind. Wählen Sie jedoch EINE Sache aus, die dringend erscheint und auf die andere am ehesten reagieren, und schlagen Sie eine Lösung vor. Wenn es funktioniert, schlagen Sie auf der Grundlage Ihres ersten Erfolgs eine andere Lösung für ein anderes Problem vor.

Aber nehmen Sie es langsam, eins nach dem anderen, und hoffen Sie, dass sich Ihre Ideen langsam in der neuen Gruppe durchsetzen.

Tom Au
quelle
2

Legen Sie das Beispiel fest, das Sie sehen möchten, aber schätzen Sie die Perspektive eines anderen Entwicklers in einem Test: Ein Entwickler testet möglicherweise auf Erfolge, während ein anderer auf Fehler testet. Ein Entwickler hat die Klasse geschrieben, während ein anderer sie beim Schreiben des Tests zum ersten Mal verwendet hat.

die vorhandenen tests (ähm, die meisten) haben noch zweck, obwohl es nicht sofort offensichtlich sein kann. ich empfehle nicht, alles auf einmal zu überholen und umzugestalten (es ist mühsam und fehleranfällig). Schlechte Tests müssen letztendlich aktualisiert, umgeschrieben oder einfach überholt werden, wenn sich die Software weiterentwickelt.

Wenn Ihr Testansatz in irgendeiner Hinsicht überlegen ist, werden die Leute von diesem Modell lernen oder Sie um Ihre Unterstützung bitten. Es wird eine ausgewogene Ressourcenverteilung geben, Sie können diese jedoch bei Bedarf erweitern, um Ihre Tests zu unterstützen.

Letztendlich möchten Sie die Qualität der Programme durch Tests steigern und die Abdeckung verbessern. Sie können dies tun, indem Sie mehr Gewicht auf das Testen legen und ein gutes Beispiel geben - aber die Perspektiven anderer schätzen.

Wenn Sie die Wichtigkeit hervorheben, können Sie die Betriebsumgebung Ihrer Tests anders gestalten. Ein naheliegendes Beispiel ist die parallele Ausführung von Tests. Wenn es nicht wiedereintrittsfähig ist, haben Sie einen Fehler in Ihrem Programm oder Test gefunden (Win / Win). Eine strengere Testumgebung zwingt dazu, die fehlerhaften Tests zu korrigieren und / oder neu zu schreiben (hoffentlich beim zweiten Mal richtig). Führen Sie solche Änderungen langsam ein (brechen Sie nicht die Hälfte der Tests auf einmal ab - das ist ein echtes Problem) und zwingen Sie sie, zu lernen, was einen guten Test und letztendlich ein gutes Programm ausmacht. Wenden Sie dann, wenn Sie und andere in Tests gehen und diese ändern / reparieren / erweitern, das an, was Sie gelernt haben - es ist inkrementell und Sie haben ein besseres Verständnis für den Kontext / das Programm zu der Zeit.

Justin
quelle
2

Repariere sie im Laufe der Zeit

Ich war in der gleichen Situation. Ich verbrachte jeden Morgen eine Stunde damit, Tests zu durchlaufen und sie zu reparieren, bis sie alle repariert waren. Es war eine mittelgroße Codebasis und ich glaube, ich war in 1,5 Monaten fertig. Auch bei unseren Tests bin ich viel sicherer geworden.

Es ist mir persönlich egal, ob ein Test ein Komponententest oder ein Integrationstest ist, solange es ein guter Test ist. Mit gutem Test meine ich, dass es:

  • räumt nach sich auf
  • ist wiederholbar
  • minimiert Umwelteinflüsse
  • ist konsistent

Unterwegs habe ich bessere Testkonstruktionen evangelisiert (das heißt, ich habe viele Leute abgehört).

dietbuddha
quelle