Angenommen, man hat ein relativ großes Programm (etwa 900.000 SLOC in C #), das alle gründlich kommentiert / dokumentiert ist, gut organisiert ist und gut funktioniert. Die gesamte Codebasis wurde von einem einzigen Senior-Entwickler geschrieben, der nicht mehr im Unternehmen ist. Der gesamte Code ist so wie er ist testbar und IoC wird durchgehend verwendet - außer aus irgendeinem seltsamen Grund haben sie keine Komponententests geschrieben. Jetzt möchte Ihr Unternehmen den Code verzweigen und Unit-Tests hinzufügen, um festzustellen, wenn Änderungen die Kernfunktionalität beeinträchtigen.
- Ist das Hinzufügen von Tests eine gute Idee?
- Wenn ja, wie würde man überhaupt mit so etwas anfangen?
BEARBEITEN
OK, also hatte ich nicht damit gerechnet, dass Antworten gute Argumente für gegensätzliche Schlussfolgerungen liefern. Das Problem kann sowieso aus meinen Händen sein. Ich habe auch die "doppelten Fragen" durchgelesen und die allgemeine Meinung ist, dass "das Schreiben von Tests gut ist" ... ja, aber in diesem speziellen Fall nicht zu hilfreich.
Ich glaube nicht, dass ich hier allein bin, um über das Schreiben von Tests für ein Altsystem nachzudenken. Ich werde Metriken darüber erstellen, wie viel Zeit aufgewendet wird und wie oft die neuen Tests Probleme aufdecken (und wie oft nicht). Ich werde wiederkommen und dies in etwa einem Jahr mit meinen Ergebnissen aktualisieren.
FAZIT
Es stellt sich also heraus, dass es im Grunde unmöglich ist, einen Unit-Test mit irgendeinem orthodoxen Anschein zu einem bestehenden Code hinzuzufügen. Sobald der Code funktioniert, können Sie Ihre Tests offensichtlich nicht rot / grün leuchten lassen. In der Regel ist nicht klar, welche Verhaltensweisen zu testen sind, wo Sie beginnen sollen und erst recht nicht, wann Sie fertig sind. Wirklich selbst diese Frage zu stellen, verfehlt in erster Linie den Hauptgrund, Tests zu schreiben. In den meisten Fällen fand ich es tatsächlich einfacher, den Code mit TDD neu zu schreiben, als die beabsichtigten Funktionen zu entschlüsseln und nachträglich in Komponententests hinzuzufügen. Wenn Sie ein Problem beheben oder eine neue Funktion hinzufügen, ist dies eine andere Geschichte, und ich glaube, dass dies der Zeitpunkt ist, um Komponententests hinzuzufügen (wie einige unten dargelegt haben). Irgendwann wird der meiste Code umgeschrieben, oft früher als erwartet.
quelle
Antworten:
Während Tests eine gute Idee sind, sollte der ursprüngliche Codierer sie erstellen, während er die Anwendung erstellte , um sein Wissen darüber zu erfassen, wie der Code funktionieren soll und was möglicherweise kaputt geht, was dann an Sie übertragen worden wäre.
Bei diesem Ansatz besteht eine hohe Wahrscheinlichkeit, dass Sie die Tests schreiben, die mit der geringsten Wahrscheinlichkeit brechen, und die meisten Randfälle übersehen, die beim Erstellen der Anwendung entdeckt worden wären.
Das Problem ist, dass der größte Teil des Werts aus diesen „Fallstricken“ und weniger offensichtlichen Situationen stammt. Ohne diese Tests verliert die Testsuite praktisch ihre gesamte Wirksamkeit. Darüber hinaus hat das Unternehmen ein falsches Sicherheitsgefühl in Bezug auf seine Anwendung, da diese nicht wesentlich regressionssicherer ist.
In der Regel müssen Tests für neuen Code und für das Refactoring alten Codes geschrieben werden, bis die alte Codebasis vollständig refactored ist.
Auch sehen .
quelle
Ja, das Hinzufügen von Tests ist definitiv eine gute Idee.
Sie sagen, es ist gut dokumentiert, und das bringt Sie in eine gute Position. Versuchen Sie, anhand dieser Dokumentation Tests zu erstellen, die sich auf Teile des Systems konzentrieren, die entweder kritisch sind oder häufigen Änderungen unterliegen.
Anfangs wird die schiere Größe der Codebasis im Vergleich zu den wenigen Tests wahrscheinlich überwältigend erscheinen, aber es gibt keinen Big-Bang-Ansatz, und es ist wichtiger, irgendwo einen Anfang zu machen, als sich zu quälen, welcher Ansatz der beste sein wird.
Ich würde Michael Feathers 'Buch Working Effectively with Legacy Code für einige gute, detaillierte Ratschläge empfehlen .
quelle
Nicht alle Komponententests haben den gleichen Nutzen. Der Vorteil eines Komponententests besteht darin, dass er fehlschlägt. Je unwahrscheinlicher das Scheitern ist, desto weniger vorteilhaft ist es. Neuer oder kürzlich geänderter Code enthält mit größerer Wahrscheinlichkeit Fehler als selten geänderter Code, der in der Produktion gut getestet wurde. Daher sind Unit-Tests für neuen oder kürzlich geänderten Code mit größerer Wahrscheinlichkeit vorteilhafter.
Nicht alle Komponententests sind gleich teuer. Es ist viel einfacher, Trivialcode zu testen, den Sie heute selbst entworfen haben, als komplexen Code, den jemand anderes vor langer Zeit entworfen hat. Auch das Testen während der Entwicklung spart normalerweise Entwicklungszeit. Bei älteren Codes ist diese Kostenersparnis nicht mehr verfügbar.
In einer idealen Welt haben Sie die Zeit, die Sie zum Testen von Legacy-Code in Einheiten benötigen. In der Realität ist es jedoch naheliegend, dass die Kosten für das Hinzufügen von Unit-Tests zu Legacy-Code die Vorteile überwiegen. Der Trick besteht darin, diesen Punkt zu identifizieren. Ihre Versionskontrolle kann Ihnen helfen, indem Sie den zuletzt geänderten und am häufigsten geänderten Code anzeigen. Sie können beginnen, indem Sie diese unter Unit-Test stellen. Wenn Sie in Zukunft Änderungen vornehmen, sollten Sie diese Änderungen und den eng damit verbundenen Code einem Komponententest unterziehen.
Wenn Sie dieser Methode folgen, werden Sie in den günstigsten Bereichen eine ziemlich gute Abdeckung haben. Wenn Sie stattdessen Monate damit verbringen, Komponententests durchzuführen, bevor Sie die umsatzgenerierenden Aktivitäten wieder aufnehmen, ist dies möglicherweise eine wünschenswerte Entscheidung für die Softwarewartung, aber eine miese Geschäftsentscheidung.
quelle
Auf jeden Fall, obwohl ich es ein bisschen schwer finde zu glauben, dass der Code sauber ist, gut funktioniert und moderne Techniken verwendet und einfach keine Komponententests hat. Sind Sie sicher, dass sie nicht in einer separaten Lösung sitzen?
Egal, wenn Sie den Code erweitern / warten möchten, sind echte Komponententests für diesen Prozess von unschätzbarem Wert.
Ein Schritt auf einmal. Wenn Sie mit Unit-Tests nicht vertraut sind, lernen Sie ein wenig. Sobald Sie mit den Konzepten vertraut sind, wählen Sie einen kleinen Teil des Codes aus und schreiben Sie Tests dafür. Dann das nächste und das nächste. Die Codeabdeckung kann Ihnen dabei helfen, Stellen zu finden, die Sie verpasst haben.
Es ist wahrscheinlich am besten, zuerst gefährliche / riskante / lebenswichtige Dinge auszuwählen, um sie zu testen, aber möglicherweise ist es effektiver, wenn Sie etwas Unkompliziertes testen, um zuerst in einen Groove zu gelangen - insbesondere, wenn Sie / das Team nicht an die Codebasis und / oder die Einheit gewöhnt sind testen.
quelle
Ja, Tests sind eine gute Idee. Sie helfen dabei, die vorhandenen Codebasis-Funktionen wie beabsichtigt zu dokumentieren und unerwartetes Verhalten zu erkennen. Selbst wenn die Tests anfangs fehlschlagen, lassen Sie sie den Code später überarbeiten, damit sie bestanden werden und sich wie beabsichtigt verhalten.
Beginnen Sie mit dem Schreiben von Tests für kleinere Klassen (solche, die keine Abhängigkeiten aufweisen und relativ einfach sind) und fahren Sie mit größeren Klassen fort (solche, die Abhängigkeiten aufweisen und komplexer sind). Es wird lange dauern, aber seien Sie geduldig und beharrlich, damit Sie die Codebasis schließlich so gut wie möglich abdecken können.
quelle
OK, ich werde die gegenteilige Meinung vertreten ...
Das Hinzufügen von Tests zu einem vorhandenen, funktionierenden System wird dieses System ändern, es sei denn, das System wurde von Anfang an mit spöttischer Absicht geschrieben. Ich bezweifle es, obwohl es durchaus möglich ist, dass es eine gute Trennung aller Komponenten mit leicht definierbaren Grenzen gibt, in die Sie Ihre nachgebildeten Schnittstellen einfügen können. Wenn dies nicht der Fall ist, müssen Sie (relativ gesehen) wichtige Änderungen vornehmen, die möglicherweise zu Problemen führen. Im besten Fall verbringen Sie viel Zeit damit, diese Tests zu erstellen. Diese Zeit könnte besser verwendet werden, um ausführliche Konstruktionsdokumente, Auswirkungsanalysen oder Lösungskonfigurationsdokumente zu erstellen. Immerhin ist das die Arbeit, die Ihr Chef mehr als Unit-Tests machen möchte. Ist es nicht
Wie auch immer, ich würde keine Unit-Tests hinzufügen.
Ich würde mich auf externe, automatisierte Testtools konzentrieren, die Ihnen eine angemessene Abdeckung bieten, ohne etwas zu ändern. Wenn Sie dann Änderungen vornehmen möchten, können Sie damit beginnen, Komponententests in die Codebasis aufzunehmen.
quelle
Ich bin oft auf diese Situation gestoßen, habe eine große Codebasis ohne ausreichende oder keine Testabdeckung geerbt und bin jetzt für das Hinzufügen von Funktionen, das Beheben von Fehlern usw. verantwortlich.
Mein Rat ist, sicherzustellen und zu testen, was Sie hinzufügen. Wenn Sie Fehler beheben oder Anwendungsfälle im aktuellen Code ändern, testet der Autor diese. Wenn Sie etwas anfassen müssen, schreiben Sie an dieser Stelle Tests.
Dies ist der Fall, wenn der vorhandene Code für Komponententests nicht gut strukturiert ist. Sie verbringen daher viel Zeit mit der Umgestaltung, um Tests für kleinere Änderungen hinzuzufügen.
quelle