Ich habe ein kleines MVC-Framework, an dem ich gearbeitet habe. Die Codebasis ist definitiv nicht groß, aber es sind nicht mehr nur ein paar Klassen. Ich habe mich schließlich entschlossen, den Sprung zu wagen und Tests dafür zu schreiben (ja, ich weiß, ich hätte das die ganze Zeit tun sollen, aber die API war bis jetzt super instabil).
Mein Plan ist es jedenfalls, das Testen extrem einfach zu machen, einschließlich Integrationstests. Ein beispielhafter Integrationstest würde in diese Richtung gehen:
Gefälschtes HTTP-Anforderungsobjekt -> MVC-Framework -> HTTP-Antwortobjekt -> Überprüfen Sie, ob die Antwort korrekt ist
Da dies alles ohne Status oder spezielle Tools (Browser-Automatisierung usw.) möglich ist, könnte ich dies mit regulären Unit-Test-Frameworks (ich verwende NUnit) problemlos durchführen.
Nun die große Frage. Wo genau soll ich die Grenze zwischen Unit-Tests und Integrationstests ziehen? Sollte ich jeweils nur eine Klasse (so oft wie möglich) mit Unit-Tests testen? Sollten Integrationstests auch im selben Testprojekt wie mein Unit-Test-Projekt platziert werden?
Antworten:
Integration vs. Unit-Tests
Sie sollten Ihre Komponententests und Ihre Integrationstests vollständig getrennt halten. Ihre Komponententests sollten nur eine Sache und eine Sache testen und den Rest Ihres Systems vollständig isolieren. Eine Einheit ist lose definiert, läuft jedoch normalerweise auf eine Methode oder eine Funktion hinaus.
Es ist sinnvoll, Tests für jede Einheit durchzuführen, damit Sie wissen, dass ihre Algorithmen korrekt implementiert sind und Sie sofort wissen, was wo schief gelaufen ist, wenn die Implementierung fehlerhaft ist.
Da Sie während des Unit-Tests vollständig isoliert testen, verwenden Sie Stub- und Mock-Objekte, um sich wie der Rest Ihrer Anwendung zu verhalten. Hier kommen Integrationstests ins Spiel. Das isolierte Testen aller Einheiten ist großartig, aber Sie müssen wissen, ob die Einheiten tatsächlich zusammenarbeiten.
Dies bedeutet zu wissen, ob ein Modell tatsächlich in einer Datenbank gespeichert ist oder ob tatsächlich eine Warnung ausgegeben wird, nachdem Algorithmus X fehlgeschlagen ist.
Testgetriebene Entwicklung
Wenn Sie einen Schritt zurücktreten und sich Test Driven Development (TDD) ansehen, müssen Sie einige Dinge berücksichtigen.
Integration zuerst gegen Integration zuletzt
Integrationstests passen auf zwei Arten in diesen TDD-Zyklus. Ich kenne Leute, die sie gerne vorher schreiben. Sie nennen einen Integrationstest einen End-to-End-Test und definieren einen End-to-End-Test als einen Test, der den gesamten Pfad eines Anwendungsfalls vollständig testet (denken Sie daran, eine Anwendung einzurichten, sie zu booten, zu einem Controller zu gehen, sie auszuführen). Überprüfung auf Ergebnis, Ausgabe usw.). Dann beginnen sie mit ihrem ersten Komponententest, lassen ihn bestehen, fügen einen zweiten hinzu, bestehen ihn usw. Langsam bestehen auch immer mehr Teile des Integrationstests, bis die Funktion abgeschlossen ist.
Der andere Stil besteht darin, einen Feature-Unit-Test nach dem anderen zu erstellen und anschließend die Integrationstests hinzuzufügen, die als notwendig erachtet werden. Der große Unterschied zwischen diesen beiden besteht darin, dass Sie beim Integrationstest zunächst über das Design einer Anwendung nachdenken müssen. Diese Art widerspricht der Annahme, dass es bei TDD sowohl um das Anwendungsdesign als auch um das Testen geht.
Praktische Aspekte
Bei mir haben wir alle unsere Tests im selben Projekt. Es gibt jedoch verschiedene Gruppen. Das Tool für die kontinuierliche Integration führt zuerst die als Komponententests gekennzeichneten Tests aus. Nur wenn diese erfolgreich sind, werden auch die langsameren Integrationstests ausgeführt (weil sie echte Anforderungen stellen, echte Datenbanken verwenden usw.).
Normalerweise verwenden wir übrigens eine Testdatei für eine Klasse.
Vorgeschlagene Literatur
quelle
Was bei jeder Teststrategie wichtig ist, ist die Testabdeckung - dh zu zeigen, dass alle Funktionen getestet werden.
Ich allgemein, und wenn Sie keine besonderen gegenteiligen Anforderungen haben (z. B. DO178 Level A, IEC61508 SIL 4 usw.), die in Ihrer Situation nicht der Fall zu sein scheinen, können Sie dann die volle Funktion der Klasse oder eines Moduls testen (und Zeigen Sie auf Systemebene, dass das Testen auf Systemebene ausreichend ist. Und so weiter runter. Unit-Tests sind nur erforderlich, wenn Sie die Tests nicht weiter oben behandelt haben.
Da Intergrationstests normalerweise einfacher, schneller und billiger sind, ziehen Sie die Grenze so weit wie möglich ...
Dies hängt wiederum vom Umfang ab. Per Definition testet ein Komponententest eine einzelne Einheit. Wenn Sie jedoch ein vollständiges Modul auf einmal vollständig testen können, tun Sie dies, wenn Sie dies wünschen. Sie erfüllen tatsächlich mehrere Komponententests mit einem Treffer.
Kein grundlegender Grund, warum nicht ... es sei denn, der Test auf höherer Ebene wird von einem unabhängigen Tester durchgeführt. Zu diesem Zeitpunkt sollten Sie nur eine ausführbare und minimale Instrumentierung ausgeben.
quelle
Wenn ich kleine Projekte habe, füge ich einfach alle Tests in dasselbe Projekt ein. Da ein größeres Projekt diese Aufteilung haben würde, stelle ich nur sicher, dass es möglich wäre, sie auseinander zu ziehen, falls es notwendig sein sollte.
Bei Unit-Tests teste ich normalerweise nur eine Klasse (SUT) in einer Datei.
quelle