unittest - unit test assertequal python




Wohin gehen die Python-Unit-Tests? (12)

Wenn Sie eine Bibliothek oder eine App schreiben, wohin gehen die Komponententestdateien?

Es ist nett, die Testdateien vom Haupt-App-Code zu trennen, aber es ist peinlich, sie in ein "tests" -Unterverzeichnis innerhalb des App-Stammverzeichnisses zu stellen, weil es den Import der zu testenden Module erschwert.

Gibt es hier eine Best Practice?


Nur 1 Testdatei

Wenn es nicht viele Testdateien gibt, ist es schön, es in ein Top-Level-Verzeichnis zu stellen (ich denke, das ist ein Python (empfohlen)):

module/
  lib/
    __init__.py
    module.py
  test.py

Viele Testdateien

Wenn viele Testdateien vorhanden sind, legen Sie sie in einen Testordner:

module/
  lib/
    __init__.py
    module.py
  tests/
    test_module.py
    test_module2.py

Wenn Sie jedoch die Tests in den __main__ kann der Test keine import ..lib in CLI import ..lib da __main__ relative Module nicht importieren kann. __main__ können wir nose , oder wir können dem Python- __main__ ein übergeordnetes Verzeichnis hinzufügen Dafür werde ich ein erstellen

env.py

import sys
import os

# append module root directory to sys.path
sys.path.append(
    os.path.dirname(
        os.path.dirname(
            os.path.abspath(__file__)
        )
    )
)

im

module/
  tests/
    test_module.py
    env.py

und import env vor dem Testimportmodul

test_module.py

import unittest
# append parent directory to import path
import env
# now we can import the lib module
from lib import module

if __name__ == '__main__':
    unittest.main()

Aufgrund meiner Erfahrung in der Entwicklung von Test-Frameworks in Python würde ich vorschlagen, Python-Unit-Tests in ein separates Verzeichnis zu stellen. Pflegen Sie eine symmetrische Verzeichnisstruktur. Dies wäre hilfreich beim Packen nur der Kernbibliotheken und nicht beim Packen der Komponententests. Unten wird durch eine schematische Darstellung umgesetzt.

                              <Main Package>
                               /          \
                              /            \
                            lib           tests
                            /                \
             [module1.py, module2.py,  [ut_module1.py, ut_module2.py,
              module3.py  module4.py,   ut_module3.py, ut_module.py]
              __init__.py]

Auf diese Weise können Sie, wenn Sie diese Bibliotheken mit einer RPM-Datei packen, nur die Hauptbibliotheksmodule (nur) packen. Dies hilft Wartungsfreundlichkeit, insbesondere in einer agilen Umgebung.


Genau diese Frage hatten wir beim Schreiben von "Py- skoscope" ( http://psychoscope.org ), das Komponententests für Python-Programme generiert. Wir haben Leute beim Testen in der Python-Liste abgefragt, bevor wir ein Verzeichnis auswählten, da gab es viele verschiedene Meinungen. Am Ende haben wir uns entschieden, ein "tests" -Verzeichnis in dasselbe Verzeichnis wie den Quellcode zu stellen. In diesem Verzeichnis erzeugen wir eine Testdatei für jedes Modul im übergeordneten Verzeichnis.


Hin und wieder schaue ich mir das Thema Testplatzierung an, und jedes Mal empfiehlt die Mehrheit eine separate Ordnerstruktur neben dem Bibliothekscode, aber ich finde, dass jedes Mal die Argumente gleich sind und nicht so überzeugend sind. Ich setze meine Testmodule irgendwo neben die Kernmodule.

Der Hauptgrund dafür ist: Refactoring .

Wenn ich Dinge umherbewege, möchte ich, dass sich Testmodule mit dem Code bewegen; Es ist leicht, Tests zu verlieren, wenn sie sich in einem separaten Baum befinden. Lassen Sie uns ehrlich sein, früher oder später haben Sie eine völlig andere Ordnerstruktur, wie django , flask und viele andere. Was ist in Ordnung, wenn es dir egal ist.

Die wichtigste Frage, die Sie sich stellen sollten, ist diese:

Schreib ich:

  • a) wiederverwendbare Bibliothek oder
  • b) ein Projekt aufbauen, anstatt einige halbgetrennte Module zusammenzufassen?

Wenn ein:

Ein separater Ordner und der zusätzliche Aufwand, um seine Struktur beizubehalten, sind möglicherweise besser geeignet. Niemand wird sich darüber beschweren, dass Ihre Tests in der Produktion eingesetzt werden .

Es ist aber genauso einfach, Tests auszuschließen, wenn sie mit den Kernordnern gemischt werden. setze dies in die setup.py :

find_packages("src", exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) 

Wenn b:

Sie können sich - wie jeder von uns - wünschen, 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 verwalten, sollte Priorität haben.

Wenn Sie dann einen guten Job gemacht haben und Ihr Modul gut zu einem anderen Projekt passt, wird es wahrscheinlich in dieses neue Projekt kopiert - nicht gespalten oder in eine separate Bibliothek umgewandelt - und die Tests, die daneben liegen, in die gleiche Ordnerstruktur verschieben ist im Vergleich zum Auffrischen von Tests in einem Durcheinander, das ein separater Testordner geworden ist, einfach. (Sie können argumentieren, dass es in erster Linie kein Chaos sein sollte, aber seien wir hier realistisch).

Die Entscheidung liegt also immer noch bei Ihnen, aber ich würde behaupten, dass Sie mit gemischten Tests die gleichen Dinge erreichen wie mit einem separaten Ordner, aber mit weniger Aufwand, um Ordnung zu halten.


Ich bevorzuge Toplevel Tests Verzeichnis. Dies bedeutet, dass Importe ein wenig schwieriger werden. Dafür habe ich zwei Lösungen:

  1. Verwende setuptools. Dann können Sie test_suite='tests.runalltests.suite' in setup() und die Tests einfach python setup.py test : python setup.py test
  2. Setze PYTHONPATH beim Ausführen der Tests: PYTHONPATH=. python tests/runalltests.py PYTHONPATH=. python tests/runalltests.py

So wird das in M2Crypto durch Code unterstützt:

Wenn Sie es vorziehen, Tests mit Nasetests durchzuführen, müssen Sie möglicherweise etwas anderes machen.


Ich empfehle Ihnen, einige Haupt-Python-Projekte auf GitHub zu überprüfen und einige Ideen zu erhalten.

Wenn der Code größer wird und Sie weitere Bibliotheken hinzufügen, ist es besser, einen Testordner in demselben Verzeichnis wie setup.py zu erstellen und die Projektverzeichnisstruktur für jeden Testtyp (Komponententest, Integration, ...) zu spiegeln.

Zum Beispiel, wenn Sie eine Verzeichnisstruktur haben wie:

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
setup.py

Nach dem Hinzufügen des Testordners haben Sie eine Verzeichnisstruktur wie:

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
test/
   unit/
      myapp/
         moduleA/
            module_A_test.py
         moduleB/
            module_B_test.py
   integration/
          myapp/
             moduleA/
                module_A_test.py
             moduleB/
                module_B_test.py
setup.py

Viele korrekt geschriebene Python-Pakete verwenden die gleiche Struktur. Ein sehr gutes Beispiel ist das Boto-Paket. Überprüfen Sie https://github.com/boto/boto


Ich habe vor kurzem begonnen, in Python zu programmieren, also hatte ich noch nicht wirklich die Chance, Best Practice zu finden. Aber ich habe ein Modul geschrieben, das alle Tests durchläuft und ausführt.

Also habe ich:

app/
 appfile.py
test/
 appfileTest.py

Ich muss sehen, wie es läuft, wenn ich zu größeren Projekten komme.


Ich neige auch dazu, meine Komponententests in die Datei selbst zu legen, wie Jeremy Cantrell oben feststellt, obwohl ich dazu tendiere, die Testfunktion nicht in den Hauptteil zu stellen, sondern alles in einen

if __name__ == '__main__':
   do tests...

Block. Dies führt dazu, dass der Datei Dokumentation als "Beispielcode" hinzugefügt wird, um die zu testende Python-Datei zu verwenden.

Ich möchte hinzufügen, dass ich dazu tendiere, sehr enge Module / Klassen zu schreiben. Wenn Ihre Module sehr viele Tests erfordern, können Sie sie in eine andere einfügen, aber selbst dann würde ich noch Folgendes hinzufügen:

if __name__ == '__main__':
   import tests.thisModule
   tests.thisModule.runtests

So kann jeder, der Ihren Quellcode liest, wissen, wo er nach dem Testcode suchen soll.


Wenn die Tests einfach sind, fügen Sie sie einfach in den Docstring ein - die meisten Test-Frameworks für Python können das verwenden:

>>> import module
>>> module.method('test')
'testresult'

Für andere ../tests/test_module.py tests/test_module.py würde ich sie entweder in ../tests/test_module.py oder in tests/test_module.py .


Wenn ich ein Paket namens "foo" schreibe, werde ich Komponententests in ein separates Paket "foo_test" schreiben. Module und Unterpakete haben dann denselben Namen wie das SUT-Paketmodul. ZB Tests für ein Modul foo.xy finden Sie in foo_test.xy Die __init__.py-Dateien jedes Testpakets enthalten dann eine AllTests-Suite, die alle Testsuiten des Pakets enthält. setuptools bietet eine bequeme Möglichkeit, das Haupttestpaket anzugeben, so dass Sie nach "python setup.py develop" einfach "python setup.py test" oder "python setup.py test -s foo_test.x.SomeTestSuite" verwenden können nur eine bestimmte Suite.


Wir gebrauchen

app / src / code.py

app / testen / code_test.py

App / Dokumente / ..

In jeder Testdatei fügen wir "../src/" in sys.path ein. Es ist nicht die schönste Lösung, aber funktioniert. Ich denke, es wäre toll, wenn jemand in Java mit Maven auftaucht, der Ihnen Standard-Konventionen gibt, die einfach funktionieren, egal welches Projekt Sie bearbeiten.


Bei einer Datei module.py sollte der test_module.py normalerweise test_module.py heißen und den Pythonic-Namenskonventionen folgen.

Es gibt mehrere allgemein akzeptierte Orte, an die test_module.py gesetzt werden test_module.py :

  1. Im selben Verzeichnis wie module.py .
  2. In ../tests/test_module.py (auf derselben Ebene wie das Code-Verzeichnis).
  3. In tests/test_module.py (eine Ebene unter dem Code-Verzeichnis).

Ich bevorzuge # 1 für seine Einfachheit, die Tests zu finden und sie zu importieren. Jedes Build-System, das Sie verwenden, kann problemlos so konfiguriert werden, dass es Dateien startet, die mit test_ . Das Standard- unittest Muster, das für die unittest verwendet wird, ist test*.py .





code-organization