Wie kann ich eine Methode testen, die die Anwesenheit einer Datei erfordert?

9

Zum ersten Mal verwende ich Python, um eine Bibliothek zu erstellen, und ich versuche, die Gelegenheit in diesem Projekt zu nutzen, Unit-Tests zu lernen. Ich habe eine erste Methode geschrieben und möchte dafür einige Unit Tests schreiben. (Ja, ich weiß, dass TDD erfordert, dass ich zuerst den Test schreibe, ich komme wirklich dorthin.)

Die Methode ist ziemlich einfach, aber es erwartet, dass die Klasse ein file Attribut-Set hat, dass das Attribut auf eine existierende Datei zeigt, und dass die Datei ein Archiv irgendeiner Art ist (derzeit nur mit Zip-Dateien arbeitend, Teer, Rar usw., die später hinzugefügt werden). Die Methode soll die Anzahl der Dateien im Archiv zurückgeben.

Ich habe in meinem Projekt einen Ordner mit dem Namen files erstellt, der ein paar Beispieldateien enthält, und ich habe die Methode manuell getestet, und sie funktioniert wie bisher. Der manuelle Test sieht folgendermaßen aus und befindet sich in der Datei archive_file.py :

%Vor%

Alles, was ich dann tue, ist sicherzustellen, dass das, was gedruckt wird, was ich erwarte angesichts des Inhalts von test.zip .

So sieht file_count aus:

%Vor%

Dies direkt in einen Komponententest zu übersetzen, erscheint mir aus einigen Gründen falsch, von denen einige möglicherweise ungültig sind. Ich zähle auf die genaue Position der Testdateien in Bezug auf die aktuelle Skriptdatei, ich brauche eine große Auswahl manuell erstellter Archivdateien, um sicherzustellen, dass ich genügend Variationen teste, und natürlich bin ich es auch den zurückgegebenen Wert manuell mit dem vergleichen, was ich erwarte, weil ich weiß, wie viele Dateien sich im Testarchiv befinden.

Es scheint mir, dass dies so viel wie möglich automatisiert werden sollte, aber es scheint auch, dass dies sehr kompliziert sein wird.

Was ist der richtige Weg, Unit-Tests für eine solche Klassenmethode zu erstellen?

    
Chuck 22.07.2016, 13:41
quelle

4 Antworten

0

Oasiscircle und dm03514 waren sehr hilfreich dabei und führten mich schließlich zur richtigen Antwort, besonders mit der Antwort von dm auf ein Folgefrage .

Was getan werden muss, ist die mock Bibliothek zu verwenden, um eine gefälschte Version von ZipFile zu erstellen, die keine Einwände gegen eine Datei hat, sondern stattdessen gültige Listen zurückgibt, wenn nameslist verwendet wird. Methode.

%Vor%

Der oben genannte __enter__.return_value -Anteil ist notwendig, weil im Code, der getestet wird, die ZipFile Instanz innerhalb eines Kontextmanagers erstellt wird.

    
Chuck 24.07.2016, 22:52
quelle
2

Es gibt so viele verschiedene Möglichkeiten, dies zu erreichen. Ich denke gerne, was wertvoll wäre, um zu testen, von ganz oben kann ich mir ein paar Dinge vorstellen:

  • Validierungslogik ( if self.file == None )
  • Bereinigungslogik
  • dass alle Dateitypen unterstützt werden, die angeblich unterstützt werden

Dieser Test könnte auf zwei Ebenen stattfinden:

  1. Testen Sie Ihre Logik
  2. Testintegration (dh unterstützte Archivtypen gegen das Dateisystem)

Unittest die Logik

Die Unteilbarkeit der Logik Ihrer Archivobjekte sollte trivial sein. Es scheint einige Tests in Ihrer file_count-Methode zu geben, die nützlich sein könnten:

  • test_no_file_returns_negative_one (Fehlerbedingungen sind "hoffentlich" nicht sehr häufig ausgeführte Codepfade und eignen sich hervorragend für Tests. Besonders, wenn Ihre Kunden diesen -1 Rückgabewert erwarten.

  • test_zip_file_pruned_logic Dies scheint eine sehr wichtige Funktionalität in Ihrem Code zu sein. Wenn sie falsch implementiert wird, würde sie die Anzahl, die Ihr Code zurückgeben kann, vollständig zurückwerfen.

  • test_happy_path_file_count_successful Ich möchte gerne einen Komponententest haben, der die ganze Funktion ausübt, indem er die gespiegelten Abhängigkeiten ZipFile verwendet, um sicherzustellen, dass alles abgedeckt ist, ohne die Integrationstests durchführen zu müssen.

Testintegrationen

Ich denke, ein Test für jeden unterstützten Archivtyp wäre sehr wertvoll. Dies können statische Fixtures sein, die in Ihrem Repo enthalten sind, und Ihre Tests würden bereits wissen, wie viele Dateien jedes Archiv besitzt und auf denen es bestehen würde.

Ich denke, dass alle Ihre Bedenken gültig sind und alle auf eine wartbare Art und Weise angesprochen und getestet werden können:

Ich zähle auf die genaue Position der Testdateien in Bezug auf die aktuelle Skriptdatei

Dies könnte durch die Konvention behoben werden, dass Ihre Datei-Fixtures in einem Unterverzeichnis Ihres Testpakets gespeichert werden und dann mit python den Dateipfad Ihres Testpakets erhalten:

FIXTURE_DIR = os.path.join(os.path.dirname(__file__), 'fixtures')

Für portablen Code ist es wichtig, diese Pfade dynamisch zu generieren.

Ich brauche eine große Auswahl manuell erstellter Archivdateien, um sicherzustellen, dass ich genügend Variationen testen kann

Ja, wie viele sind gut genug? MINDESTENS ein Test pro unterstütztem Archivtyp. (Netflix muss gegen jedes einzelne Gerät testen, auf dem sie eine App haben :), viele Unternehmen müssen Tests gegen große Matrix von mobilen Geräten durchführen) Ich denke, dass die Testabdeckung hier entscheidend ist, aber versuchen Sie, all die Randfälle dazu zu bringen müssen in Unit Tests abgedeckt werden.

Ich vergleiche den zurückgegebenen Wert manuell mit dem, was ich erwarte, weil ich weiß, wie viele Dateien sich im Testarchiv befinden.

Das Archiv muss statisch werden und Ihr Test speichert diese Informationen.

Eine Sache, die Sie im Auge behalten sollten, sind die Bereiche Ihrer Tests. Einen Test zu machen, der ZipFile ausübt, wäre nicht sehr wertvoll, weil er in der stdlibrary ist und bereits Tests hat. Darüber hinaus wäre es wahrscheinlich auch nicht sehr hilfreich zu testen, ob Ihr Code mit allen Python-Dateisystemen / os 'zusammenarbeitet, da Python bereits diese Überprüfungen hat.

Aber Ihre Tests zu überprüfen, um zu überprüfen, ob Ihre Anwendung mit allen Dateitypen funktioniert, die sie unterstützt, ist meiner Meinung nach äußerst wertvoll, weil es ein Vertrag zwischen Ihnen und Ihren Kunden ist. "Hey, das funktioniert, lasst mich zeig dir ". Genauso wie Pythons Tests ein Vertrag zwischen Ihnen und Ihnen sind, der sagt: "Hey, wir unterstützen OSX / LINUX / was auch immer ich Ihnen zeigen darf"

    
dm03514 22.07.2016 16:38
quelle
0

Schlagen Sie vor, die Löschlogik in eine separate Methode umzuwandeln, die nicht von Datei oder Zipfile abhängt. Dies:

%Vor%

Wird:

%Vor%

Jetzt können Sie prune_dirs ohne Testdateien testen.

%Vor%

Wenn Sie Integrationstests vermeiden möchten, müssen Sie ZipFile fälschen oder nachahmen. In diesem Fall würde jedes Objekt, das die Methodennamenliste () bereitstellt, ausreichen.

%Vor%

Jetzt führe ich eine neue Methode get_helper () in ArchiveFile

ein %Vor%

... und überschreiben Sie get_helper () in einer Child-Testklasse.

%Vor%

Mit einer Testklasse überschreiben Sie genau das, was Sie von ArchiveFile benötigen, um die Abhängigkeit von ZipFile zu beseitigen. Verwenden Sie in Ihrem Test die Testklasse und ich denke, dass Sie eine gute Abdeckung haben.

%Vor%

Sie werden wahrscheinlich über Möglichkeiten nachdenken wollen, die Namensliste zu ändern, damit Sie mehr Fälle als die hier gezeigte testen können.

    
Jeremy Thien 22.07.2016 18:41
quelle
0

Mocking funktioniert.
Ein anderer Ansatz ist das Einrichten einer Umgebung.

Für Ihren Anwendungsfall würde das Einrichten einer Umgebung das Erstellen eines temporären Verzeichnisses, das Kopieren von Dateien, die dort zu erwarten sind, und das Ausführen von Tests darin bedeuten.

Sie müssen einen Parameter oder ein globales Element hinzufügen, das Ihrem Code mitteilt, in welches Verzeichnis er schauen soll.

Das hat sehr gut für mich funktioniert. Mein Anwendungsfall ist jedoch insofern etwas anders, als ich Tests für Code schreibe, der ein externes Programm verwendet, also habe ich keine Möglichkeit, etwas zu verspotten.

    
toolforger 20.11.2017 19:20
quelle

Tags und Links