Ich folge TDD religiös. Meine Projekte haben in der Regel eine Testabdeckung von mindestens 85% mit aussagekräftigen Testfällen.
Ich arbeite viel mit HBase , und die Haupt-Client-Oberfläche, HTable, ist ein echtes Problem. Das Schreiben meiner Komponententests dauert drei- oder viermal länger als das Schreiben von Tests, die einen Live-Endpunkt verwenden.
Ich weiß, dass Tests, die Mocks verwenden, aus philosophischer Sicht Vorrang vor Tests haben sollten, die einen Live-Endpunkt verwenden. Aber das Verspotten von HTable ist ein schwerwiegender Schmerz, und ich bin mir nicht sicher, ob es einen großen Vorteil gegenüber dem Testen mit einer Live-HBase-Instanz bietet.
Jeder in meinem Team führt eine Einzelknoten-HBase-Instanz auf seiner Workstation aus, und auf unseren Jenkins-Boxen werden Einzelknoten-HBase-Instanzen ausgeführt, sodass es nicht auf die Verfügbarkeit ankommt. Die Live-Endpunkttests dauern offensichtlich länger als die Tests, die Mocks verwenden, aber das interessiert uns nicht wirklich.
Im Moment schreibe ich Live-Endpunkttests UND mockbasierte Tests für alle meine Klassen. Ich würde gerne die Mocks fallen lassen, aber ich möchte nicht, dass die Qualität infolgedessen abnimmt.
Was denkst du alle?
quelle
Antworten:
Meine erste Empfehlung wäre, Typen, die Sie nicht besitzen , nicht zu verspotten . Sie haben erwähnt, dass HTable ein echtes Problem ist - vielleicht sollten Sie es stattdessen in einen Adapter einwickeln, der die 20% der von Ihnen benötigten Funktionen von HTable verfügbar macht, und den Wrapper bei Bedarf verspotten.
Angenommen, wir sprechen von Typen, die Sie alle besitzen. Wenn sich Ihre mockbasierten Tests auf glückliche Pfadszenarien konzentrieren, in denen alles reibungslos verläuft, verlieren Sie nichts, weil Ihre Integrationstests wahrscheinlich bereits genau dieselben Pfade testen.
Isolierte Tests werden jedoch interessant, wenn Sie darüber nachdenken, wie Ihr zu testendes System auf alle im Vertrag des Mitarbeiters definierten Vorgänge reagieren soll, unabhängig davon, mit welchem konkreten Objekt es tatsächlich zu tun hat. Das ist ein Teil dessen, was manche als grundlegende Korrektheit bezeichnen . Es könnte viele dieser kleinen Fälle und viele weitere Kombinationen geben. Hier werden Integrationstests langsam mies, während isolierte Tests schnell und einfach zu handhaben sind.
Was passiert konkret, wenn eine der Methoden Ihres HTable-Adapters eine leere Liste zurückgibt? Was ist, wenn es null zurückgibt? Was ist, wenn eine Verbindungsausnahme ausgelöst wird? Es sollte im Vertrag des Adapters festgelegt werden, ob eine dieser Situationen eintreten könnte, und ein Verbraucher sollte darauf vorbereitet sein, mit diesen Situationen umzugehen , weshalb Tests für diese Situationen erforderlich sind.
Fazit: Sie werden keinen Qualitätsverlust feststellen, wenn Sie Ihre mockbasierten Tests entfernen, wenn sie genau die gleichen Tests wie Ihre Integrationstests durchführen . Der Versuch, sich zusätzliche Einzeltests (und Vertragstests ) vorzustellen, kann Ihnen dabei helfen, Ihre Schnittstellen / Verträge gründlich zu überdenken und die Qualität zu steigern, indem Sie Fehler beheben, die schwer zu überlegen und / oder mit Integrationstests nur langsam zu testen wären.
quelle
Ich denke zumindest, das ist ein Punkt, an dem TDD-Befürworter derzeit kontrovers diskutiert werden.
Meine persönliche Meinung geht darüber hinaus, dass ein mockbasierter Test meistens eine Art Schnittstellenvertrag darstellt ; im Idealfall bricht es, wenn und nur wenn Sie die Schnittstelle ändern . Als solches ist es in relativ stark typisierten Sprachen wie Java und bei Verwendung einer explizit definierten Schnittstelle fast völlig überflüssig: Der Compiler hat Ihnen bereits mitgeteilt, ob Sie die Schnittstelle geändert haben.
Die Hauptausnahme ist, wenn Sie eine sehr allgemeine Benutzeroberfläche verwenden, die möglicherweise auf Anmerkungen oder Überlegungen basiert und die der Compiler nicht automatisch überwachen kann. Selbst dann sollten Sie überprüfen, ob es eine Möglichkeit gibt, die Validierung programmgesteuert (z. B. eine SQL-Syntaxprüfungsbibliothek) und nicht manuell mithilfe von Mocks durchzuführen.
Dies ist der letztere Fall, den Sie durchführen, wenn Sie mit einer "Live" -Lokaldatenbank testen. Die Implementierung von htable beginnt und führt eine viel umfassendere Validierung des Schnittstellenvertrags durch, als Sie jemals gedacht hätten, dies von Hand zu schreiben.
Leider ist der Test, dass:
Solche Tests sollten natürlich sofort gelöscht werden.
quelle
Wie lange dauert die Ausführung eines endpunktbasierten Tests als eines scheinbasierten Tests? Wenn es erheblich länger dauert, lohnt es sich, Zeit für das Schreiben von Tests zu investieren, um die Komponententests zu beschleunigen - denn Sie müssen sie viele Male ausführen. Wenn es nicht wesentlich länger dauert, obwohl es sich bei den endpunktbasierten Tests nicht um "reine" Einheitentests handelt, gibt es keinen Grund, religiös zu sein, solange sie die Einheit gut testen.
quelle
Ich bin mit der Antwort von guillaume31 völlig einverstanden, verspotte niemals Typen, die du nicht besitzt !.
Normalerweise spiegelt ein Testschmerz (das Verspotten einer komplexen Benutzeroberfläche) ein Problem in Ihrem Design wider. Möglicherweise benötigen Sie eine gewisse Abstraktion zwischen Ihrem Modell und Ihrem Datenzugriffscode, beispielsweise mithilfe einer hexagonalen Architektur und eines Repository-Musters, um diese Art von Problemen zu lösen.
Wenn Sie einen Integrationstest zur Überprüfung durchführen möchten, führen Sie einen Integrationstest durch. Wenn Sie einen Komponententest durchführen möchten, weil Sie Ihre Logik testen, führen Sie einen Komponententest durch und isolieren Sie die Persistenz. Aber wenn Sie einen Integrationstest durchführen, weil Sie nicht wissen, wie Sie Ihre Logik von einem externen System isolieren können (oder weil es ein Problem ist), ist dies ein großer Geruch. Sie wählen Integration anstelle von Einheit, da Ihr Design nur begrenzt ist und keine wirklichen Anforderungen bestehen um die Integration zu testen.
Schauen Sie sich dieses Gespräch von Ian Cooper an: http://vimeo.com/68375232 , er spricht über sechseckige Architektur und Tests, er spricht darüber, wann und was verspottet werden soll, ein wirklich inspiriertes Gespräch, das viele Fragen wie Ihre über echtes TDD löst .
quelle
TL; DR - Wie ich das sehe, hängt davon ab, wie viel Aufwand Sie für Tests aufwenden und ob es besser gewesen wäre, mehr davon für Ihr tatsächliches System auszugeben.
Lange Version:
Hier einige gute Antworten, aber ich nehme es anders an: Testen ist eine wirtschaftliche Aktivität, die sich auszahlen muss, und wenn die von Ihnen aufgewendete Zeit nicht für die Entwicklung und Systemzuverlässigkeit aufgewendet wird (oder für alles andere, was Sie herausfinden möchten) von Tests), dann können Sie eine schlechte Investition machen; Sie sind im Bauwesen tätig und schreiben keine Tests. Daher ist die Reduzierung des Aufwands zum Schreiben und Verwalten von Tests von entscheidender Bedeutung.
Einige der wichtigsten Werte, die ich durch Tests erhalte, sind:
Das Testen gegen einen Live-Endpunkt sollte diese weiterhin bereitstellen.
Einige Nachteile beim Testen mit einem Live-Endpunkt:
Wenn ich mich in dieser Situation befände und die Nachteile kein Problem zu sein schienen, während das Verspotten des Endpunkts mein Testschreiben erheblich verlangsamte, würde ich sofort gegen einen Live-Endpunkt testen, solange ich mir sicher bin, dass dies der Fall ist Überprüfen Sie nach einiger Zeit erneut, ob die Nachteile in der Praxis kein Problem darstellen.
quelle
Aus der Sicht der Tests gibt es einige Anforderungen, die ein absolutes Muss sind:
Dies ist eine große Herausforderung, wenn Sie eine Verbindung zu einer Quelle herstellen, die den Status außerhalb Ihrer Tests beibehält. Es ist kein "reines" TDD, aber die Ruby on Rails-Crew hat dieses Problem auf eine Weise gelöst, die möglicherweise für Ihre Zwecke angepasst werden kann. Das Rails Test Framework funktionierte folgendermaßen:
All diese Arbeiten wurden in das Testgeschirr eingebaut und funktionieren recht gut. Es steckt noch viel mehr dahinter, aber die Grundlagen reichen für dieses Gespräch aus.
In den verschiedenen Teams, mit denen ich im Laufe der Zeit zusammengearbeitet habe, haben wir Entscheidungen getroffen, die das Testen von Code fördern, auch wenn dies nicht der richtige Weg ist. Im Idealfall würden wir alle Aufrufe an einen Datenspeicher mit dem von uns gesteuerten Code umschließen. Theoretisch könnten wir, wenn eines dieser alten Projekte neue Mittel erhalten würde, zurückgehen und es von einer datenbankgebundenen zu einer Hadoop-gebundenen Aufgabe machen, indem wir unsere Aufmerksamkeit auf nur eine Handvoll Klassen konzentrieren.
Wichtig ist, dass Sie sich nicht mit den Produktionsdaten anlegen und sicherstellen, dass Sie wirklich das testen, was Sie zu testen glauben. Es ist sehr wichtig, den externen Dienst bei Bedarf auf einen bekannten Basiswert zurücksetzen zu können - auch von Ihrem Code aus.
quelle