Wenn Sie eine Bibliothek oder eine App schreiben, wohin gehen die Unit-Test-Dateien?
Es ist schön, die Testdateien vom Haupt-App-Code zu trennen, aber es ist umständlich, sie in einem Unterverzeichnis "tests" im App-Stammverzeichnis abzulegen, da es schwieriger ist, die zu testenden Module zu importieren.
Gibt es hier eine bewährte Methode?
python
unit-testing
code-organization
Schreibgeschützt
quelle
quelle
Antworten:
Für eine Datei
module.py
sollte dertest_module.py
Komponententest normalerweise gemäß den Pythonic-Namenskonventionen aufgerufen werden.Es gibt mehrere allgemein akzeptierte Orte
test_module.py
:module.py
.../tests/test_module.py
(auf derselben Ebene wie das Codeverzeichnis).tests/test_module.py
(eine Ebene unter dem Codeverzeichnis).Ich bevorzuge # 1 wegen seiner Einfachheit, die Tests zu finden und zu importieren. Welches Build-System Sie auch verwenden, es kann einfach so konfiguriert werden, dass Dateien beginnend mit ausgeführt werden
test_
. Tatsächlich ist das Standardmusterunittest
für die Testerkennungtest*.py
.quelle
Nur 1 Testdatei
Wenn nur 1 Testdatei vorhanden ist, wird empfohlen, diese in einem Verzeichnis der obersten Ebene abzulegen:
Führen Sie den Test in der CLI aus
Viele Testdateien
Wenn viele Testdateien vorhanden sind, legen Sie diese in einem
tests
Ordner ab:Führen Sie den Test in der CLI aus
Verwenden
unittest discovery
unittest discovery
findet alle Tests im Paketordner.Erstellen Sie einen
__init__.py
In-tests/
OrdnerFühren Sie den Test in der CLI aus
Referenz
pytest
Gute Praktiken für das Testlayoutunittest
Unit Test Framework
quelle
Es ist üblich, das Testverzeichnis im selben übergeordneten Verzeichnis wie Ihr Modul / Paket abzulegen. Wenn Ihr Modul also foo.py heißt, sieht Ihr Verzeichnislayout folgendermaßen aus:
Natürlich gibt es keinen Weg, dies zu tun. Sie können auch ein Test-Unterverzeichnis erstellen und das Modul mit dem absoluten Import importieren .
Wo immer Sie Ihre Tests durchführen, würde ich empfehlen, dass Sie die Nase verwenden , um sie auszuführen. Nose durchsucht Ihre Verzeichnisse nach Tests. Auf diese Weise können Sie Tests dort durchführen, wo sie organisatorisch am sinnvollsten sind.
quelle
Wir hatten die gleiche Frage beim Schreiben von Pythoscope ( https://pypi.org/project/pythoscope/ ), das Unit-Tests für Python-Programme generiert. Wir haben Leute zu den Tests in der Python-Liste befragt, bevor wir ein Verzeichnis ausgewählt haben. Es gab viele verschiedene Meinungen. Am Ende haben wir uns entschieden, ein "Tests" -Verzeichnis in dasselbe Verzeichnis wie den Quellcode zu stellen. In diesem Verzeichnis generieren wir eine Testdatei für jedes Modul im übergeordneten Verzeichnis.
quelle
Ich neige auch dazu, meine Komponententests in die Datei selbst zu schreiben, wie Jeremy Cantrell oben bemerkt, obwohl ich dazu neige, die Testfunktion nicht in den Hauptteil zu stellen, sondern alles in eine
Block. Dies führt dazu, dass der Datei Dokumentation als 'Beispielcode' für die Verwendung der zu testenden Python-Datei hinzugefügt wird.
Ich sollte hinzufügen, ich neige dazu, sehr enge Module / Klassen zu schreiben. Wenn Ihre Module eine sehr große Anzahl von Tests erfordern, können Sie sie in eine andere einfügen, aber selbst dann würde ich noch hinzufügen:
Auf diese Weise weiß jeder, der Ihren Quellcode liest, wo er nach dem Testcode suchen muss.
quelle
Hin und wieder überprüfe ich das Thema der Testplatzierung, und jedes Mal empfiehlt die Mehrheit eine separate Ordnerstruktur neben dem Bibliothekscode, aber ich finde, dass die Argumente jedes Mal gleich und nicht so überzeugend sind. Am Ende platziere ich meine Testmodule irgendwo neben den Kernmodulen.
Der Hauptgrund dafür ist: Refactoring .
Wenn ich Dinge bewege, möchte ich, dass sich Testmodule mit dem Code bewegen. Es ist leicht, Tests zu verlieren, wenn sie sich in einem separaten Baum befinden. Seien wir ehrlich, früher oder später haben Sie eine völlig andere Ordnerstruktur wie Django , Kolben und viele andere. Was in Ordnung ist, wenn es dich nicht interessiert.
Die Hauptfrage, die Sie sich stellen sollten, lautet:
Schreibe ich:
Wenn ein:
Ein separater Ordner und der zusätzliche Aufwand zur Aufrechterhaltung seiner Struktur sind möglicherweise besser geeignet. Niemand wird sich darüber beschweren, dass Ihre Tests für die Produktion bereitgestellt werden .
Es ist aber genauso einfach, Tests von der Verteilung auszuschließen, wenn sie mit den Kernordnern gemischt werden. füge dies in die setup.py ein :
Wenn b:
Sie möchten vielleicht - wie jeder von uns -, dass Sie wiederverwendbare Bibliotheken schreiben, aber die meiste Zeit ist ihr Leben an das Leben des Projekts gebunden. Die Fähigkeit, Ihr Projekt einfach zu warten, sollte Priorität haben.
Wenn Sie dann gute Arbeit geleistet haben und Ihr Modul für ein anderes Projekt gut geeignet ist, wird es wahrscheinlich in dieses neue Projekt kopiert - nicht gegabelt oder in eine separate Bibliothek verschoben - und Tests verschoben, die daneben in derselben Ordnerstruktur liegen ist einfach im Vergleich zum Auffischen von Tests in einem Durcheinander, zu dem ein separater Testordner geworden war. (Sie können argumentieren, dass es in erster Linie kein Chaos sein sollte, aber lassen Sie uns hier realistisch sein).
Sie haben also immer noch die Wahl, aber ich würde argumentieren, dass Sie mit gemischten Tests dieselben Ergebnisse erzielen wie mit einem separaten Ordner, jedoch mit weniger Aufwand, um die Dinge sauber zu halten.
quelle
Ich verwende ein
tests/
Verzeichnis und importiere dann die Hauptanwendungsmodule mit relativen Importen. In MyApp / tests / foo.py könnte es also Folgendes geben:um das
MyApp.foo
Modul zu importieren .quelle
Ich glaube nicht, dass es eine etablierte "Best Practice" gibt.
Ich habe meine Tests in einem anderen Verzeichnis außerhalb des App-Codes abgelegt. Ich füge dann das Hauptverzeichnis der App zu sys.path hinzu (damit Sie die Module von überall importieren können) in meinem Testrunner-Skript (das auch einige andere Aufgaben ausführt), bevor ich alle Tests ausführe. Auf diese Weise muss ich das Testverzeichnis nie aus dem Hauptcode entfernen, wenn ich es freigebe, was mir Zeit und Mühe spart, wenn auch nur eine winzige Menge.
quelle
os.sys.path.append(os.dirname('..'))
Aufgrund meiner Erfahrung bei der Entwicklung von Test-Frameworks in Python würde ich vorschlagen, Python-Unit-Tests in einem separaten Verzeichnis abzulegen. Pflegen Sie eine symmetrische Verzeichnisstruktur. Dies wäre hilfreich, wenn nur die Kernbibliotheken und nicht die Komponententests verpackt werden sollen. Das Folgende wird durch ein schematisches Diagramm implementiert.
Auf diese Weise können Sie beim Packen dieser Bibliotheken mit einer Drehzahl nur die Hauptbibliotheksmodule (nur) packen. Dies trägt zur Wartbarkeit insbesondere in agilen Umgebungen bei.
quelle
Ich empfehle Ihnen, einige der wichtigsten Python-Projekte auf GitHub zu überprüfen und einige Ideen zu erhalten.
Wenn Ihr Code größer wird und Sie mehr Bibliotheken hinzufügen, ist es besser, einen Testordner in demselben Verzeichnis zu erstellen, in dem Sie setup.py haben, und Ihre Projektverzeichnisstruktur für jeden Testtyp zu spiegeln (unittest, Integration, ...).
Zum Beispiel, wenn Sie eine Verzeichnisstruktur haben wie:
Nach dem Hinzufügen des Testordners haben Sie eine Verzeichnisstruktur wie:
Viele richtig geschriebene Python-Pakete verwenden dieselbe Struktur. Ein sehr gutes Beispiel ist das Boto-Paket. Überprüfen Sie https://github.com/boto/boto
quelle
matplotlib
hat es zum Beispiel untermatplotlib/lib/matplotlib/tests
( github.com/matplotlib/matplotlib/tree/… ),sklearn
hat es unterscikitelearn/sklearn/tests
( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )Wie ich es mache...
Ordnerstruktur:
Setup.py zeigt auf src / als Speicherort meiner Projektmodule, dann starte ich:
Dadurch wird mein Projekt in Site-Pakete eingefügt und auf meine Arbeitskopie verwiesen. Um meine Tests durchzuführen, benutze ich:
Verwenden Sie den von mir konfigurierten Testläufer.
quelle
code.py
. Es wäre sinnvoller, das Verzeichnis der obersten Ebene "Projekt" zu nennen.Ich bevorzuge Toplevel-Testverzeichnis. Dies bedeutet, dass Importe etwas schwieriger werden. Dafür habe ich zwei Lösungen:
test_suite='tests.runalltests.suite'
in gehensetup()
und die Tests einfach ausführen:python setup.py test
PYTHONPATH=. python tests/runalltests.py
So wird dieses Zeug von Code in M2Crypto unterstützt:
Wenn Sie lieber Tests mit Nasentests durchführen möchten, müssen Sie möglicherweise etwas anderes tun.
quelle
Wir gebrauchen
In jede Testdatei fügen wir
../src/
einsys.path
. Es ist nicht die schönste Lösung, funktioniert aber. Ich denke, es wäre großartig, wenn jemand mit so etwas wie Maven in Java auftauchen würde, das Ihnen Standardkonventionen gibt, die einfach funktionieren, egal an welchem Projekt Sie arbeiten.quelle
Wenn die Tests einfach sind, fügen Sie sie einfach in die Dokumentzeichenfolge ein - die meisten Test-Frameworks für Python können dies verwenden:
Für andere komplexere Tests würde ich sie entweder ein-
../tests/test_module.py
oder einfügentests/test_module.py
.quelle
In C # habe ich die Tests im Allgemeinen in eine separate Assembly aufgeteilt.
In Python habe ich bisher entweder Doctests geschrieben, bei denen sich der Test in der Dokumentzeichenfolge einer Funktion befindet, oder sie in den
if __name__ == "__main__"
Block am unteren Rand des Moduls eingefügt .quelle
Wenn ich ein Paket namens "foo" schreibe, werde ich Unit-Tests in ein separates Paket "foo_test" einfügen. Module und Unterpakete haben dann denselben Namen wie das SUT-Paketmodul. Beispielsweise finden sich Tests für ein Modul foo.xy in foo_test.xy. Die Dateien __init__.py jedes Testpakets enthalten dann eine AllTests-Suite, die alle Testsuiten des Pakets enthält. setuptools bietet eine bequeme Möglichkeit, das Haupttestpaket anzugeben, sodass Sie nach "python setup.py development" einfach "python setup.py test" oder "python setup.py test -s foo_test.x.SomeTestSuite" verwenden können nur eine bestimmte Suite.
quelle
Ich lege meine Tests in dasselbe Verzeichnis wie den zu testenden Code (CUT). für
foo.py
die Tests wird infoo_ut.py
oder ähnlich sein. (Ich optimiere den Testerkennungsprozess, um diese zu finden.)Dadurch werden die Tests direkt neben dem Code in einer Verzeichnisliste angezeigt, wodurch deutlich wird, dass Tests vorhanden sind, und das Öffnen der Tests wird so einfach wie möglich, wenn sie sich in einer separaten Datei befinden. (Für Befehlszeileneditoren
vim foo*
und bei Verwendung eines grafischen Dateisystembrowsers klicken Sie einfach auf die CUT-Datei und dann auf die unmittelbar benachbarte Testdatei.)Wie andere bereits betont haben , erleichtert dies auch das Refactorisieren und Extrahieren des Codes zur Verwendung an anderer Stelle, falls dies jemals erforderlich sein sollte.
Ich mag die Idee, Tests in einen völlig anderen Verzeichnisbaum zu stellen, wirklich nicht. Warum ist es für Entwickler schwieriger als nötig, die Tests zu öffnen, wenn sie die Datei mit dem CUT öffnen? Es ist nicht so, dass die überwiegende Mehrheit der Entwickler so sehr daran interessiert ist, Tests zu schreiben oder zu optimieren, dass sie jede Barriere ignorieren, anstatt die Barriere als Ausrede zu benutzen. (Im Gegenteil, meiner Erfahrung nach kenne ich viele Entwickler, die sich nicht die Mühe machen, Tests zu schreiben, selbst wenn Sie es so einfach wie möglich machen.)
quelle
Ich habe vor kurzem angefangen, in Python zu programmieren, daher hatte ich noch keine Chance, die besten Praktiken herauszufinden. Aber ich habe ein Modul geschrieben, das alle Tests findet und ausführt.
Also habe ich:
Ich werde sehen müssen, wie es geht, wenn ich zu größeren Projekten übergehe.
quelle