Übung

Abgeschlossen

In dieser Übung verwenden Sie pytest mit parametrisieren, um eine Funktion zu testen. Anschließend aktualisieren Sie eine Testklasse, um anstelle einer setup()- und einer teardown()-Methode eine Fixture zu verwenden. Durch die Verwendung von Parametrisieren und Arbeiten mit Leuchten können Sie flexibler werden, wenn Sie Tests erstellen oder aktualisieren.

Schritt 1: Hinzufügen einer Datei mit Tests für diese Übung

  1. Erstellen Sie eine neue Testdatei namens test_advanced.py , und fügen Sie den folgenden Code hinzu:

    def str_to_bool(string):
        if string.lower() in ['yes', 'y', '1']:
            return True
        elif string.lower() in ['no', 'n', '0']:
            return False
    
    

    Die Funktion str_to_bool() akzeptiert eine Zeichenfolge als Eingabe, und abhängig von ihrem Inhalt gibt sie einen True- oder False-Wert zurück.

  2. Fügen Sie in derselben Datei die Tests für die Funktion str_to_bool() an: Verwenden Sie pytest.mark.parametrize(), um zuerst alle true-Werte zu testen:

    import pytest 
    
    @pytest.mark.parametrize("string", ['Y', 'y', '1', 'YES'])
    def test_str_to_bool_true(string):
        assert str_to_bool(string) is True
    
  3. Fügen Sie als Nächstes einen weiteren Test mit den false-Werten an:

    @pytest.mark.parametrize("string", ['N', 'n', '0', 'NO'])
    def test_str_to_bool_false(string):
        assert str_to_bool(string) is False
    

    Es gibt nun zwei Tests, die alle möglichen Eingaben für die True- und False-Rückgabewerte abdecken.

Hinweis

Es ist nicht üblich, Tests innerhalb derselben Datei wie tatsächlichen Code aufzubewahren. Die Beispiele in dieser Übung verfügen der Einfachheit halber über tatsächlichen Code in derselben Datei. In realen Python-Projekten sehen Sie, dass Tests durch Dateien und Verzeichnisse vom Testcode getrennt sind.

Schritt 2: Ausführen der Tests und Erkunden des Berichts

Nachdem Sie die Tests hinzugefügt haben, besteht der nächste Schritt darin, pytest auszuführen und die Ausgabe zu prüfen. Verwenden Sie das Flag für erhöhte Ausführlichkeit (-v), damit alle Eingabewerte als separater Test behandelt werden können.

$ pytest -v test_avanced.py
============================= test session starts ==============================
Python 3.9.6, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 
rootdir: /private
collected 8 items

test_advanced.py::test_str_to_bool_true[Y] PASSED                        [ 12%]
test_advanced.py::test_str_to_bool_true[y] PASSED                        [ 25%]
test_advanced.py::test_str_to_bool_true[1] PASSED                        [ 37%]
test_advanced.py::test_str_to_bool_true[YES] PASSED                      [ 50%]
test_advanced.py::test_str_to_bool_false[N] PASSED                       [ 62%]
test_advanced.py::test_str_to_bool_false[n] PASSED                       [ 75%]
test_advanced.py::test_str_to_bool_false[0] PASSED                       [ 87%]
test_advanced.py::test_str_to_bool_false[NO] PASSED                      [100%]

============================== 8 passed in 0.01s ===============================

Obwohl Sie nur zwei Testfunktionen geschrieben haben, konnte pytest dank der parametrize()-Funktion insgesamt acht Tests erstellen.

Schritt 3: Portieren eines vorhandenen Tests an eine Fixture

  1. Fügen Sie der datei test_advanced.py einen neuen klassenbasierten Test hinzu. Dieser Test sollte eine setup()- und eine teardown()-Funktion verwenden, die eine temporäre Datei mit etwas Text erstellt. Nach jedem Test wird die Datei entfernt. Diese sollte wie folgt aussehen:

    import os
    
    
    class TestFile:
    
        def setup(self):
            with open("/tmp/done", 'w') as _f:
                _f.write("1")
    
        def teardown(self):
            try:
                os.remove("/tmp/done")
            except OSError:
                pass
    
        def test_done_file(self):
            with open("/tmp/done") as _f:
                contents = _f.read()
            assert contents == "1"
    

    Diese Testklasse erstellt eine Datei, ist jedoch problematisch, da der Pfad /tmp/ nicht garantiert auf jedem System vorhanden ist.

  2. Erstellen Sie eine Einrichtung, welche die pytesttmpdir()-Fixture zum Schreiben in die Datei verwendet und geben Sie den Pfad zurück:

    import pytest
    
    @pytest.fixture
    def tmpfile(tmpdir):
        def write():
            file = tmpdir.join("done")
            file.write("1")
            return file.strpath
        return write
    

    Die tmpfile()-Fixture verwendet die tmpdir()-Fixture von Pytest, die eine gültige temporäre Datei garantiert, die nach Abschluss der Tests bereinigt wird.

  3. Aktualisieren Sie die TestFile Klasse so, dass sie die Vorrichtung anstelle der Hilfsmethoden verwendet:

    class TestFile:
    
        def test_f(self, tmpfile):
            path = tmpfile()
            with open(path) as _f:
                contents = _f.read()
            assert contents == "1"
    

    Diese Testklasse kann jetzt sicherstellen, dass eine temporäre Datei erstellt wird und über den richtigen Inhalt für die Assertion verfügt.

Arbeit überprüfen

Jetzt sollten Sie über eine Python-Datei namens test_advanced.py mit dem folgenden Code verfügen:

  • Eine str_to_bool()-Funktion, die eine Zeichenfolge akzeptiert und je nach Inhalt der Zeichenfolge einen booleschen Wert zurückgibt.
  • Zwei parametrisierte Tests für die str_to_bool()-Funktion, einer, der die True-Werte und der andere, der die False-Werte testet.
  • Eine benutzerdefinierte pytest Vorrichtung, die die tmpdir() Vorrichtung verwendet, um eine temporäre done Datei mit einigen Inhalten zu erstellen.
  • Eine Testklasse, die die benutzerdefinierte tmpfile()-Fixture zum Erstellen der Datei verwendet.

Alle Tests sollten ohne Fehler bestanden werden, wenn sie im Terminal ausgeführt werden.