Was sind konkrete Vorteile für ordnungsgemäße Unit-Tests gegenüber Funktionstests, die als Unit-Tests bezeichnet werden?

9

Ein Projekt, an dem ich arbeite, enthält eine Reihe von Legacy-Tests, die nicht richtig verspottet wurden. Aus diesem Grund ist EasyMock die einzige Abhängigkeit, die keine Statik, Konstruktoren mit Argumenten usw. unterstützt. Die Tests basieren stattdessen auf Datenbankverbindungen und dergleichen, um die Tests "auszuführen". Das Hinzufügen von Powermock zur Behandlung dieser Fälle wird als kostenintensiv eingestuft, da das vorhandene Projekt aktualisiert werden muss, um es zu unterstützen (eine weitere Diskussion).

Meine Fragen sind, was sind die WIRKLICHEN Vorteile der richtigen Einheitentests, die ich verwenden kann, um zurückzudrängen? Sind da welche? Bin ich nur ein Stickler, indem ich sage, dass schlechte Unit-Tests (auch wenn sie funktionieren) schlecht sind? Ist die Codeabdeckung genauso effektiv?

Jackie
quelle
3
Möglicherweise könnte der Code, den Sie schreiben, von einigen strukturellen Änderungen profitieren, um ihn testbarer zu machen. Wir setzen in unserer Einrichtung ausgiebig Unit-Tests ohne spöttischen Rahmen ein, und es scheint für uns ziemlich gut zu funktionieren.
Robert Harvey
Wow, ich bin beeindruckt, dass ich interessiert sein würde, wie Sie dies mit der JAR-Integration von Drittanbietern verwalten. Haben Sie Beispiele oder Links?
Jackie
1
Wir verwenden keine JAR-Integration von Drittanbietern. :) Wir erstellen jedoch nach Bedarf Stubs. Mocking Frameworks sind nur eine Annehmlichkeit, um dasselbe zu erreichen. Wenn sich dieser Prozess jedoch als zu mühsam herausstellt, überdenken wir unseren Codierungsansatz.
Robert Harvey

Antworten:

8
  • Ressourcen

    Sie benötigen eine Testdatenbank, um die Tests auszuführen. Die Hardware zum Ausführen der Datenbank ist teurer als die Verwendung von Powermock. Durch die Freigabe der für Unit-Tests verwendeten Ressourcen für die Datenbank muss das Unternehmen den Server nicht so schnell aktualisieren.

  • Verlässlichkeit

    Ein Test kann fehlschlagen, weil die Datenbank inaktiv ist oder sich in einem inkonsistenten Zustand befindet. Ratet mal, Ihre Builds sind fehlgeschlagen, weil die DBAs den Entwicklungsserver tagsüber heruntergefahren haben, um einige Upgrades durchzuführen (und jetzt versuchen die Entwickler herauszufinden, was im Code schief gelaufen ist - wenn es nicht der Code ist).

  • Zusätzliche Wartung

    Tests können in beliebiger Reihenfolge ausgeführt werden. Das Hinzufügen oder Entfernen eines Tests sollte nicht dazu führen, dass die Testsuite fehlschlägt. Das Ausführen einer Datenbank bedeutet, dass irgendwo (in der Datenbank) ein Status vorhanden ist. In der Regel erfordern diese Tests zusätzliche Wartung, um sicherzustellen, dass die Datenbank den richtigen Status für den nächsten Test beibehält.

  • Parallelität

    Zwei Entwickler führen die Komponententests gleichzeitig durch. Eine Datenbank bedeutet, dass die Tests in der Datenbank kollidieren können. Die Lösung hierfür wäre, die Datenbank für jeden ausgeführten Test zu klonen, was für eine reale Datenbank unzulässig ist. Was zu einer weiteren Option führt.

Erwägen Sie auch, HSQLDB mit dem von Ihnen verwendeten Datenbankdialekt zu verwenden. Auf diese Weise kann für jeden Test eine In-Memory-Datenbank erstellt werden. Ein Komponententest wird ausgeführt, erstellt die erforderliche Datenbank, lädt die Daten, die Datenbankverbindung aus dem Code stellt eine Verbindung zu HSQLDB her und wird mit den Testdaten ausgeführt.

Roc Martí
quelle
4

Meine Fragen sind, was sind die WIRKLICHEN Vorteile der richtigen Einheitentests, die ich verwenden kann, um zurückzudrängen?

Gute Unit-Tests sind (gemäß Clean Code und anderswo):

  • Schnell
  • Unabhängig
  • Wiederholbar
  • Selbstvalidierend
  • Rechtzeitig

Wenn keine echten Komponententests durchgeführt werden, werden die ersten drei (und normalerweise die letzten) verletzt. Dies führt zu einigen ziemlich bedeutenden Problemen:

  1. Ihre Tests sind langsam. Langsame Tests werden selten ausgeführt. Tests, die nicht ausgeführt werden, sind fast nutzlos.
  2. Ihre Tests können aus Gründen fehlschlagen, die nicht mit dem zu testenden Code zusammenhängen. Dies macht es weitaus schwieriger herauszufinden, warum Tests fehlgeschlagen sind, Zeit zu verschwenden und die Leute dazu zu bringen, die Umwelt und nicht den Code zu beschuldigen.
  3. Wenn sich die Datenbank ändert, ändern sich Ihre Ergebnisse. Es ist mühsam, ärgerlich und fehleranfällig, eine Datenbank für Tests in einen bekanntermaßen konsistenten, gepflegten Zustand zu bringen.

Im Allgemeinen führt ein Mangel an Isolation bei Komponententests zu schlechteren Tests, deren Schreiben länger dauert, deren Untersuchung länger dauert und die weniger Vertrauen in Ihre Codebasis bieten. Das wiederum führt dazu, dass Leute weniger Tests schreiben oder die Tests mehr ignorieren, was die Abwärtsspirale zum Chaos darstellt.

Telastyn
quelle
2

Unit-Tests sind nur ein Tool, mit dem Entwickler zuverlässigen Code bereitstellen können. Wenn Sie so denken, wie Ihr Chef denkt, können Sie ihn davon überzeugen, ob das, was Sie vorschlagen, Sinn macht. Wenn Sie es jedoch als Evangelist auf einem Bandwagen präsentieren, erhalten Sie nicht die zugewiesenen Ressourcen. Sie müssen ihm erklären, wie er davon profitiert, wenn Sie Zeit und Ressourcen für die Nachrüstung von Komponententests für Ihre Legacy-Anwendung aufwenden.

Sie haben Legacy-Tests erwähnt - das impliziert Legacy-Code. Leider ist das Anpassen von Komponententests an Code, der nicht für Komponententests ausgelegt ist, ein schwieriger, zeitaufwändiger und teurer Prozess. Der Business Case wird noch schwieriger, wenn Sie Tests haben, die nützliche Ergebnisse liefern, und alles, was Sie erreichen werden, sind (aus dem Business Case POV) alternative Tests, die dieselben Ergebnisse liefern. Sie müssen sich auf die Kosten- (Zeit-) Einsparungen konzentrieren .....

Ich vermute, dass Sie Ihrem Chef keinen soliden Business Case präsentieren können, weil es keinen gibt.

mattnz
quelle
Ich kann definitiv sehen, woher Sie kommen, aber ich habe mehr nach Möglichkeiten gesucht, diesen Business Case zu erstellen. Nicht nur die Sorge um die Qualität am Rande ist unerschwinglich.
Jackie
1

Nach dem, was Sie beschrieben haben, klingt es so, als ob Sie Testframework A nicht mögen und zu Testframework B wechseln möchten, die beide funktionieren. Nehmen Sie es auf und verwenden Sie das, was vorhanden ist und funktioniert. Erstellen Sie keine weitere Arbeit, um das Rad neu zu erfinden, damit Sie Ihr bevorzugtes Test-Framework verwenden können.

Es ist mehr als nur der Wunsch, die neueste Version des Monats zu verwenden, um zu rechtfertigen, dass vorhandener Arbeitscode weggeworfen wird und viel Zeit und Geld aufgewendet wird, um den Benutzern im Wesentlichen keinen Nutzen zu bringen.

Ryathal
quelle
Nicht genau diese sind keine Materie des Frameworks und eher eine Materie, die es Tests ermöglicht, auf andere Ressourcen zuzugreifen. Dadurch werden sie im Wesentlichen zu Funktionstests anstelle von Komponententests. Die "Frameworks" sind sowohl JUnit als auch EasyMock (wenn auch ältere Versionen). Ich habe vorgeschlagen, ein NEUES abhängiges Framework hinzuzufügen.
Jackie
1

Gute Unit-Tests ermöglichen die Lokalisierung. Funktionstests können Ihnen sagen, dass "die Funktion zum Hinzufügen eines Benutzers fehlerhaft ist", aber ein guter Komponententest zeigt Ihnen, dass sie fehlerhaft ist, weil jemand das Feld USER.LAST_NAME in der Datenbank so geändert hat, dass es nicht null ist. Es ist auch möglich, kleine Änderungen direkt zu testen, anstatt eine komplexe Testumgebung zu benötigen (die für einige Tests möglicherweise neu initialisiert oder gelöscht werden muss).

TMN
quelle