Ich arbeite mit folgendem System:
Network Data Feed -> Third Party Nio Library -> My Objects via adapter pattern
Wir hatten kürzlich ein Problem, bei dem ich die von mir verwendete Version der Bibliothek aktualisiert habe. Dies führte unter anderem dazu, dass Zeitstempel (die von der Bibliothek eines Drittanbieters zurückgegeben werden long
) von Millisekunden nach der Epoche auf Nanosekunden nach der Epoche geändert wurden.
Das Problem:
Wenn ich Tests schreibe, die die Objekte der Drittanbieterbibliothek verspotten, ist mein Test falsch, wenn ich bei den Objekten der Drittanbieterbibliothek einen Fehler gemacht habe. Zum Beispiel habe ich nicht bemerkt, dass sich die Genauigkeit der Zeitstempel geändert hat, was dazu führte, dass der Komponententest geändert werden musste, da mein Modell die falschen Daten zurückgab. Dies ist kein Fehler in der Bibliothek , es ist passiert, weil ich etwas in der Dokumentation verpasst habe.
Das Problem ist, ich kann nicht sicher sein, welche Daten in diesen Datenstrukturen enthalten sind, da ich ohne einen echten Datenfeed keine echten generieren kann. Diese Objekte sind groß und kompliziert und enthalten viele verschiedene Daten. Die Dokumentation für die Drittanbieter-Bibliothek ist schlecht.
Die Frage:
Wie kann ich meine Tests einrichten, um dieses Verhalten zu testen? Ich bin nicht sicher, ob ich dieses Problem in einem Komponententest lösen kann, da der Test selbst leicht falsch sein kann. Darüber hinaus ist das integrierte System groß und kompliziert und es ist leicht, etwas zu übersehen. In der obigen Situation hatte ich beispielsweise das Timestamp-Handling an mehreren Stellen korrekt angepasst, aber einen davon habe ich verpasst. Das System schien in meinem Integrationstest hauptsächlich die richtigen Dinge zu tun, aber als ich es für die Produktion bereitstellte (mit viel mehr Daten), wurde das Problem offensichtlich.
Ich habe momentan keinen Prozess für meine Integrationstests. Testen ist im Wesentlichen: Versuchen Sie, die Einheitentests in Ordnung zu halten, fügen Sie weitere Tests hinzu, wenn Probleme auftreten, und stellen Sie sie dann auf meinem Testserver bereit. Stellen Sie sicher, dass die Dinge vernünftig erscheinen. Dieses Problem mit dem Zeitstempel bestand die Komponententests, da die Mocks falsch erstellt wurden, und bestand dann den Integrationstest, weil keine unmittelbaren, offensichtlichen Probleme aufgetreten sind. Ich habe keine QS-Abteilung.
Timestamp
Rückklasse (mit einem beliebigen Darstellung sie wollen) und liefert genannte Verfahren (.seconds()
,.milliseconds()
,.microseconds()
,.nanoseconds()
) und natürlich den Namen Konstrukteure. Dann hätte es keine Probleme gegeben.Antworten:
Es hört sich so an, als ob Sie bereits Due Diligence betreiben. Aber ...
Nehmen Sie auf der praktischsten Ebene immer eine gute Handvoll der beiden Integrationstests für die vollständige Schleife für Ihren eigenen Code in Ihre Suite auf und schreiben Sie mehr Behauptungen, als Sie für nötig halten. Insbesondere sollten Sie über eine Handvoll Tests verfügen, die einen vollständigen Zyklus zum Erstellen, Lesen und Validieren ausführen.
Und es hört sich so an, als würdest du schon so etwas machen. Sie haben es nur mit einer schuppigen und / oder komplizierten Bibliothek zu tun. In diesem Fall empfiehlt es sich, einige Testarten "So funktioniert die Bibliothek" einzufügen, die sowohl Ihr Verständnis der Bibliothek bestätigen als auch als Beispiele für die Verwendung der Bibliothek dienen.
Angenommen, Sie müssen verstehen und davon abhängig sein, wie ein JSON-Parser jeden "Typ" in einer JSON-Zeichenfolge interpretiert. Es ist hilfreich und trivial, so etwas in Ihre Suite aufzunehmen:
Denken Sie aber auch daran, dass automatisierte Tests jeglicher Art und bei nahezu jeder Genauigkeit Sie immer noch nicht vor allen Fehlern schützen können. Es ist durchaus üblich, Tests hinzuzufügen, wenn Sie Probleme entdecken. Da es keine QA-Abteilung gibt, werden viele dieser Probleme von den Endbenutzern entdeckt.
Und zu einem erheblichen Teil ist das ganz normal.
Und drittens, wenn eine Bibliothek die Bedeutung eines Rückgabewerts oder Feldes ändert, ohne das Feld oder die Methode umzubenennen oder auf andere Weise abhängigen Code zu "brechen" (möglicherweise durch Ändern des Typs), wäre ich mit diesem Herausgeber verdammt unzufrieden. Und ich würde argumentieren, dass Sie, obwohl Sie wahrscheinlich das Changelog hätten lesen sollen, wenn es eines gibt, wahrscheinlich auch einen Teil Ihres Stresses an den Verlag weitergeben sollten. Ich würde behaupten, sie brauchen die hoffentlich konstruktive Kritik ...
quelle
(new JSONParser()).parse(datastream)
, da sie die Daten direkt von aNetworkInterface
abrufen und alle Klassen, die das eigentliche Parsen durchführen, paketprivat und geschützt sind.NetworkInterface
... ist es etwas, in das Sie Daten einspeisen können, indem Sie die Schnittstelle mit einem Port auf localhost verbinden oder so?NetworkInterface
. Es ist ein Low-Level-Objekt zum direkten Arbeiten mit einer Netzwerkkarte und zum Öffnen von Sockets usw.Kurze Antwort: Es ist schwer. Sie haben wahrscheinlich das Gefühl, dass es keine guten Antworten gibt, und das liegt daran, dass es keine einfachen Antworten gibt.
Lange Antwort: Wie @ptyx sagt , benötigen Sie Systemtests und Integrationstests sowie Komponententests :
Einige konkrete Vorschläge:
Ich habe Programmieren als Lernaktivität für ein Problem und einen Lösungsraum beschrieben. Es ist vielleicht nicht möglich, alles im Voraus perfekt zu machen, aber Sie können es später lernen. ("Ich habe die Zeitstempelbehandlung an mehreren Stellen behoben, aber eine verpasst. Kann ich meine Datentypen oder Klassen ändern, um die Zeitstempelbehandlung expliziter und schwerer zu gestalten, oder um sie zentraler zu gestalten, sodass ich nur eine Stelle ändern kann? Kann ich Änderungen vornehmen Meine Tests zur Überprüfung weiterer Aspekte der Zeitstempelverarbeitung Kann ich meine Testumgebung vereinfachen, um dies in Zukunft zu vereinfachen? Kann ich mir ein Tool vorstellen, das dies vereinfacht hätte, und wenn ja, kann ich ein solches Tool bei Google finden? " Etc.)
quelle
Ich bin absolut anderer Meinung als Sie hier. Es ist ein Fehler in der Bibliothek , in der Tat ein ziemlich heimtückischer. Sie haben den semantischen Typ des Rückgabewerts geändert, aber nicht den programmatischen Typ des Rückgabewerts. Dies kann alle Arten von Chaos anrichten, insbesondere, wenn es sich um eine geringfügige Beule handelt, aber auch, wenn es sich um eine größere Beule handelt.
Angenommen, die Bibliothek hat stattdessen einen Typ zurückgegeben
MillisecondsSinceEpoch
, einen einfachen Wrapper, der ein enthältlong
. Wenn sie es in einenNanosecondsSinceEpoch
Wert geändert hätten, wäre Ihr Code nicht kompiliert worden und hätte Sie offensichtlich auf die Stellen hingewiesen, an denen Sie Änderungen vornehmen müssen. Die Änderung konnte Ihr Programm nicht unbemerkt beschädigen.Besser noch wäre ein
TimeSinceEpoch
Objekt, das seine Schnittstelle anpassen könnte, da mehr Präzision hinzugefügt wurde, z. B. das Hinzufügen einer#toLongNanoseconds
Methode neben der#toLongMilliseconds
Methode, ohne dass der Code geändert werden muss.Das nächste Problem ist, dass Sie keine zuverlässigen Integrationstests für die Bibliothek haben. Sie sollten diese schreiben. Besser wäre es, eine Schnittstelle um diese Bibliothek herum zu erstellen, um sie vom Rest Ihrer Anwendung abzukapseln. Mehrere andere Antworten sprechen dies an (und mehr tauchen auf, während ich tippe). Integrationstests sollten seltener ausgeführt werden als Unit-Tests. Deshalb hilft eine Pufferschicht. Teilen Sie Ihre Integrationstests in einen separaten Bereich ein (oder benennen Sie sie anders), damit Sie sie nach Bedarf ausführen können, jedoch nicht jedes Mal, wenn Sie Ihren Komponententest ausführen.
quelle
...Ex()
Methoden in der Win32API). Wenn dies nicht möglich ist, wäre es besser gewesen, den Vertrag durch Umbenennen der Funktion (oder ihres Rückgabetyps) zu "brechen", als das Verhalten zu ändern.Sie benötigen Integrations- und Systemtests.
Unit-Tests eignen sich hervorragend, um zu überprüfen, ob sich Ihr Code erwartungsgemäß verhält. Wie Sie feststellen, stellt dies weder Ihre Annahmen in Frage noch stellt es sicher, dass Ihre Erwartungen vernünftig sind.
Es sei denn, Ihr Produkt hat nur eine geringe Interaktion mit externen Systemen oder es interagiert mit Systemen, die so gut bekannt, stabil und dokumentiert sind, dass sie zuverlässig verspottet werden können (dies ist in der Praxis selten der Fall) - Unit-Tests reichen nicht aus.
Je höher Ihre Tests sind, desto mehr schützen sie Sie vor dem Unerwarteten. Dies ist mit Kosten verbunden (Bequemlichkeit, Geschwindigkeit, Sprödigkeit ...), sodass Komponententests die Grundlage Ihrer Tests bleiben sollten, Sie jedoch andere Ebenen benötigen, einschließlich - möglicherweise - ein winziges Stück menschlicher Tests, die einen großen Beitrag zum Fangen leisten dumme Dinge, über die niemand nachdachte.
quelle
Am besten erstellen Sie einen minimalen Prototyp und verstehen, wie die Bibliothek genau funktioniert. Auf diese Weise erhalten Sie einige Kenntnisse über die Bibliothek mit einer schlechten Dokumentation. Ein Prototyp kann ein minimalistisches Programm sein, das diese Bibliothek verwendet und die Funktionalität übernimmt.
Andernfalls macht es keinen Sinn, Komponententests mit halb definierten Anforderungen und einem schwachen Verständnis des Systems zu schreiben.
Was Ihr spezielles Problem betrifft - über die Verwendung falscher Metriken: Ich würde es als eine Änderung der Anforderungen behandeln. Wenn Sie das Problem erkannt haben, ändern Sie die Komponententests und den Code.
quelle
Wenn Sie eine beliebte, stabile Bibliothek verwenden, können Sie vielleicht davon ausgehen, dass sie Ihnen keine bösen Streiche spielt. Aber wenn Dinge wie das, was Sie beschrieben haben, mit dieser Bibliothek passieren, dann ist dies offensichtlich keine. Nach dieser schlechten Erfahrung müssen Sie jedes Mal, wenn bei Ihrer Interaktion mit dieser Bibliothek etwas schief geht, nicht nur die Möglichkeit untersuchen, dass Sie einen Fehler gemacht haben, sondern auch die Möglichkeit, dass die Bibliothek einen Fehler gemacht hat. Angenommen, dies ist eine Bibliothek, bei der Sie sich "unsicher" sind.
Eine der Techniken, die bei Bibliotheken angewendet werden, bei denen wir uns "unsicher" sind, besteht darin, eine Zwischenschicht zwischen unserem System und diesen Bibliotheken aufzubauen, die die von den Bibliotheken angebotenen Funktionen abstrahiert, die unsere Erwartungen an die Bibliothek für richtig hält und die auch erheblich vereinfacht Für unser zukünftiges Leben sollten wir beschließen, dieser Bibliothek den Start zu geben und sie durch eine andere Bibliothek zu ersetzen, die sich besser verhält.
quelle
assert
Schlüsselwort (oder die Funktion oder Einrichtung, je nachdem, welche Sprache Sie verwenden) ist Ihr Freund. Ich spreche nicht von Behauptungen in den Unit- / Integrationstests. Ich sage, dass die Isolationsschicht mit Behauptungen sehr schwer sein sollte, um alles zu behaupten, was über das Verhalten der Bibliothek behauptet werden kann.