Nach vorne
Ich habe viele Dinge gelesen, bevor ich diese Frage gestellt habe, einschließlich vieler relevanter Fragen hier auf SE:
- (Software Engineering SE) Schreiben von Tests für Code, dessen Zweck ich nicht verstehe
- (Software Engineering SE) Unit-Test-Neuling-Team muss Unit-Test durchführen
- (Software Engineering SE) Best Practices für die Nachrüstung von Legacy-Code mit automatisierten Tests
- (Software Engineering SE) Wie teste ich große Legacy-Systeme?
- (Blog-Beitrag) So verspotten Sie Ihre Unit-Test-Umgebung
Ich kann jedoch nicht anders, als das Gefühl zu haben, dass der Juckreiz noch nicht zerkratzt wurde, nachdem ich um Hilfe gelesen habe.
TL; DR
Wie schreibe ich Komponententests für Legacy-Code, den ich nicht ausführen, simulieren, lesen oder leicht verstehen kann? Welche Regressionstests sind für eine Komponente nützlich, die vermutlich wie beabsichtigt funktioniert?
Das ganze Bild
Ich bin wieder ein zurückkehrender Sommerpraktikant, als ich in die Graduiertenschule übergehe. Meine Aufgabe beinhaltet folgende Anforderungen:
- Bewerten Sie für ein bestimmtes Produkt, ob unser Softwareteam die IDE- und JUnit-Version aktualisieren kann, ohne die Kompatibilität mit den vorhandenen Projekten zu verlieren.
- Entwickeln Sie Komponententests für eine Komponente im vorhandenen Java-Code (es handelt sich größtenteils nicht um Java). Wir möchten das Software-Team davon überzeugen, dass Unit-Tests und TDD unschätzbare Werkzeuge sind, die sie verwenden sollten. (Derzeit besteht eine Codeabdeckung von 0%.)
- Beenden Sie irgendwie die Tage der Cowboy-Codierung für ein kritisches System.
Nachdem ich eine Kopie des Quellcodes erhalten hatte, habe ich versucht, ihn zu erstellen und auszuführen, damit ich verstehe, was dieses Produkt tut und wie es funktioniert. Ich konnte nicht. Ich habe meine Vorgesetzten gefragt, wie es mir geht, und mir wurde ein neuer eigenständiger Computer ausgestellt, der in der Lage ist, ihn zu erstellen, einschließlich der tatsächlich erstellten Build-Skripte. Das hat auch nicht funktioniert, da der Produktionscode erwartungsgemäß nur auf dem eingebetteten System ausgeführt wird, für das er entwickelt wurde. Da sie jedoch einen Simulator für diesen Zweck haben, haben sie den Simulator erhalten und ihn für mich auf diese Maschine gestellt. Der Simulator funktionierte auch nicht. Stattdessen erhielt ich endlich einen Ausdruck einer GUI für einen bestimmten Bildschirm. Sie haben auch keine Codekommentare innerhalb des über 700.000 Java LOC, was das Erfassen noch schwieriger macht. Außerdem, Es gab Probleme bei der Bewertung, ob ihre Projekte mit neueren IDEs kompatibel waren oder nicht. Insbesondere wurde ihr Code nicht richtig in die von ihnen verwendete IDE-Version geladen.
Mein Inventar sieht folgendermaßen aus:
- NetBeans 8, 9, 10, 11
- Einheit 4, 5
- Ihr Quellcode für ein bestimmtes Produkt (enthält mehr als 700.000 Java LOC)
- Praktisch keine Codekommentare (gelegentlich eine Signatur)
- Keine vorhandenen Tests
- Ein physisches Foto eines GUI-Fensters
- Ein Software-Design-Dokument (109 S.), in dem die Komponente im Bild nicht behandelt wird
Ich habe zumindest genug, um theoretisch Tests zu schreiben, die ausgeführt werden können. Also habe ich einen grundlegenden Unit-Test für diese Komponente versucht. Ich konnte jedoch die Objekte, die es als Abhängigkeiten gab, nicht initialisieren, einschließlich Modelle, Manager und DB-Verbindungen. Ich habe nicht viel Erfahrung mit JUnit, abgesehen von grundlegenden Unit-Tests. Folgen Sie mir also zum nächsten Abschnitt.
Was ich aus meiner Lektüre gelernt habe
- Verspotten: Wenn ich einen Komponententest schreibe, müssen wahrscheinlich Scheinvariablen für Produktionsabhängigkeiten vorhanden sein, in denen ich nicht einfach initialisieren kann
setUp
. - Jeder hier schlägt großzügig das Buch "Effektiv mit Legacy-Code arbeiten" von Michael Feathers vor.
- Regressionstests sind wahrscheinlich ein guter Anfang. Ich glaube nicht, dass ich genug Waffen habe, um Integrationstests durchzuführen, und Regressionstests würden unser Softwareteam sofort befriedigen. Ich habe jedoch keinen Zugriff auf die bekannten Fehler. aber ich könnte möglicherweise fragen.
Und jetzt ein Versuch, die Unsicherheit, die ich noch habe, als Frage zu artikulieren. Im Wesentlichen verstehe ich nicht, wie das Schreiben dieser Tests funktioniert . Vorausgesetzt, ich erhalte (wahrscheinlich) keine weitere Anleitung von meinen Vorgesetzten, liegt es in meinem Umfeld, nicht nur zu lernen, was diese Komponente tut, sondern zu entscheiden, welche Tests tatsächlich als Regressionstests nützlich sind.
Können Sie als Fachleute, die länger als ich mit solchen Projekten gearbeitet haben, Anleitungen zum Schreiben von Komponententests in solchen Situationen geben?
quelle
How do I write unit tests for legacy code that I can't build, run, simulate, read about, or otherwise understand?
- Das kannst du nicht. Sie müssen zumindest wissen, wie hoch die erwartete Ausgabe für eine bestimmte Eingabe ist.Antworten:
In erster Näherung sind die Stakeholder einer Testsuite die Codeentwickler / -betreuer. Du wirst etwas Zeit brauchen. Bestehen Sie darauf.
Fragen Sie sie nach Problemen, mit denen sie konfrontiert sind.
Fragen Sie sie nach Fehlern, die sie kürzlich behoben haben (in den letzten Jahren, vorausgesetzt, dies ist ein langes, langsames Projekt).
Ich habe den Eindruck, dass Sie nicht erwarten, dass sie für Ihre Arbeit liebenswürdig sind. Vielleicht hast du Recht. Aber ich glaube nicht, dass man ohne ihre Hilfe etwas Nützliches bauen kann.
Sie werden Ihre Hand halten, indem Sie den ersten Test schreiben. Vielleicht ziehst du sie, aber du hältst Hände in beide Richtungen.
Sobald Sie einen Test haben, wird hoffentlich klarer, wie der zweite zu schreiben ist. Wenn Sie es geschafft haben, irgendeine Art von Beziehung aufzubauen, wird es sicherlich klarer.
quelle
Ich gehe davon aus, dass Sie den Code irgendwann zum Kompilieren bringen können. Wenn Sie nicht einmal so weit kommen können, sind Sie auf der Suche nach einem Narren.
Das Fehlen geeigneter Anforderungen, Spezifikationen oder Screenshots ist kein Blocker für das Schreiben von Tests. Solange Sie den Quellcode lesen können, können Sie Tests schreiben.
Wenn Sie die Berechtigung erhalten, die Codebasis umzugestalten, um beispielsweise Datenbankverbindungen hinter ihrer eigenen Schnittstelle zu isolieren, können Sie einige Black-Box-Komponententests schreiben. Schreiben Sie im Grunde Tests, um Eingaben in eine Methode zu werfen und deren Verhalten oder Ausgabe zu bestätigen. Holen Sie sich Tests für jede Codezeile in einer Methode und lassen Sie dann eines der leitenden Mitglieder des Teams Ihre Tests überprüfen.
Wenn Sie nicht die Berechtigung erhalten, die Codebasis für das Schreiben von Komponententests umzugestalten, sind vollständige Integrationstests oder UI-Automatisierungstests Ihre einzige Option. Selbst dann ist Black-Box-Testen Ihre beste Strategie - werfen Sie einige Eingaben auf die Benutzeroberfläche und sehen Sie, wie sie reagiert. Machen Sie Ihre Behauptungen. Lassen Sie Ihre Tests von einem hochrangigen Teammitglied überprüfen.
Irgendwann werden Sie über genügend automatisierte Tests verfügen, damit Sie mit der Umgestaltung der Codebasis beginnen können, um Unit-Tests einzuführen. Die UI-Tests stellen sicher, dass die wichtigsten Anwendungsfälle für Unternehmen funktionieren. Anschließend können Sie eine Architektur nachrüsten, die für Tests auf Einheiten- oder Komponentenebene geeignet ist.
Ein weiterer Vorteil von UI-Tests besteht darin, dass Sie bei Ihrem Team den Ruf aufbauen können, dass Sie die Codebasis verstehen, was sie wiederum offener für Änderungen macht, da der Beweis im Pudding liegt. Und Sie haben Pudding gemacht, indem Sie bestandene Tests geschrieben haben.
Zusamenfassend:
Sie werden überrascht sein, wie schnell Sie die Gesamtansicht einer 700.000-Zeilen-Anwendung erlernen können
quelle
Basierend auf der Beschreibung des Problems und Ihren Kommentaren denke ich, dass das Beste, was Sie tun können, darin besteht, mit der Java-API zu beginnen und zu versuchen, einen einzelnen Komponententest um eine isolierte Methode herum zu erstellen.
Ohne Zugriff auf den Code kann ich Ihnen nur eine eingeschränkte Anleitung geben, aber ich würde nach etwas suchen, das darin a) keine Abhängigkeiten aufweist, b) keine Statusänderungen vornimmt. Zum Beispiel. Angenommen, es gibt eine Methode, die einen Wert annimmt und überprüft, ob er in einen bestimmten Bereich fällt. Wenn Sie etwas ohne Abhängigkeiten nicht finden können, versuchen Sie etwas, das einen Wert aus einer Abhängigkeit abruft, und versuchen Sie, ihn zu verspotten.
Sobald Sie so etwas Kleines gefunden haben, können Sie mit dem Erstellen von Tests beginnen. Wenn die Methode einen positiven Wert testet, übergeben Sie einen negativen Wert und stellen Sie sicher, dass er ihn abfängt usw. Das Problem hierbei ist, dass Sie möglicherweise nicht genau wissen, wie das richtige Verhalten ist. Möglicherweise müssen Sie um Hilfe bitten oder die Dokumentation dafür durchforsten.
Es ist unwahrscheinlich, dass Sie damit sehr weit kommen. Die Realität ist, dass das Schreiben von Code, damit er einem Unit-Test unterzogen werden kann, eine Kunst für sich ist. Code, der nicht in diesem Sinne geschrieben wurde, kann für Unit-Tests schwierig bis unmöglich sein.
Eine weitere Option, die möglicherweise einfacher implementiert werden kann, ist das Testen der Binärkompatibilität. Das heißt, Sie erfassen die Ein- und Ausgänge eines Systems und geben dann zum Testen dieselben Ein- und Ausgänge ein und vergleichen die Ausgänge. Dies sagt Ihnen nicht, ob der Code zu Beginn richtig oder falsch ist, kann jedoch dazu beitragen, Regressionsfehler zu erkennen, bei denen sich bei einer anderen Änderung unbeabsichtigt Änderungen ergeben haben. Sie müssen jedoch in der Lage sein, die gesamte Anwendung auszuführen, um dies zu erreichen.
quelle