Übergabe dynamischer Objekte vom Setup an die Testfunktion in py.test

In großen Projekten tritt irgendwann eine Situation auf, in der bereits viele Tests für das Projekt durchgeführt wurden und sich parallel dazu ein eigenes übergeordnetes Framework entwickelt. Das Framework in diesem Fall als Wrapper über die Funktionen des Testobjekts und die Funktionen verschiedener Tools, die im Projekt verwendet werden. Darüber hinaus sind alle Ordner mit Fixtures gefüllt, von denen viele nur in einer Testdatei verwendet werden.



In diesem wunderbaren Moment treten einige Probleme auf. Ich habe bereits über einen von ihnen geschrieben, dies ist die Implementierung einer bequemen Parametrisierung, zum Beispiel aus einer Datei . Wir werden über den nächsten der unglücklichsten in diesem Artikel sprechen.



"Captain, wir haben viele Spielpaarungen und es erscheinen Globals."



Das Überladen von Testverzeichnissen mit Fixtures ist eine logische Konsequenz der Verwendung des in py.test enthaltenen Konzepts, aber manchmal geht dieser Ansatz über das Akzeptable hinaus. Darüber hinaus können wir häufig Konstruktionen in Tests beobachten, mit denen ermittelt werden soll, welche Informationen ein Test in einem bestimmten Fall benötigt, oder der Wunsch, zunächst die Möglichkeit zu prüfen, den Test in der Phase der Vorbereitung der Umgebung weiter zu bestehen.



Das größte Missverständnis in einer Situation, in der diese Konstrukte von einem setupGerät übergeben werden und den gesamten Test durchlaufen, ist die Verwendung von globalVariablen. Ich habe ähnliche schwierige Fälle erlebt und diese Idee ist eine der ersten, die mir in den Sinn kommen.



Es ist an dieser Stelle erwähnenswert, dass das Konzept der Fixtures diesen Makel der Code-Sauberkeit vermeidet, aber auch zusätzliche Abstraktionsebenen und viele Referenzen bietet. Als letztes Mittel können Sie die schreckliche Angewohnheit haben, das Ergebnis eines Geräts auszupacken, aber in diesem Fall verderben wir die Protokolle, weil Wir haben keine Unterteilung in Setup, Run und Teardown und komplizieren zusätzlich den Code zum Zeitpunkt des Entpackens der Ergebnisse oder der Erstellung mehrerer Verknüpfungen.



Schauen wir uns einige Beispiele an und beginnen wir mit dem Schlimmsten:



"Fixtures and Global"



import pytest

@pytest.fixture(autouse=True)
def setup(create_human, goto_room, goto_default_position, choose_window, get_current_view):
    global human
    global window

    #   
    desired_room = 1 #    ,    
    human = create_human("John", "Doe") #          
  
    #  -    ,     
    assert goto_room(human, desired_room), "{}     {}".format(human.full_name, desired_room)
    
    #   
    window = choose_window(desired_room)
    view = get_current_view(window)
    assert view, "  {}  ".format (window)
    
    yield
    #  Teardown    
    goto_default_position(human)

@pytest.mark.parametrize(
    "city, expected_result",
    [
        ("New York", False), 
        ("Berlin", False),
        ("Unknown", True)
    ]
)
def test_city_in_window(city, expected_result):
    """       ."""
    window_view = human.look_into(window)
    recognized_city = human.recognize_city(window_view)
    assert (recognized_city == city) == expected_result, "    "


Ergebend:



  • Es gibt erste Überprüfungen
  • Es gibt ein Unglück global


" "



import pytest

@pytest.fixture
def setup(create_human, goto_room, goto_default_position, choose_window, get_current_view):
    #   
    desired_room = 1 #    ,    
    human = create_human("John", "Doe") #          
  
    #  -    ,     
    assert goto_room(human, desired_room), "{}     {}".format(human.full_name, desired_room)
    
    #   
    window = choose_window(desired_room)
    view = get_current_view(window)
    assert view, "  {}  ".format (window)
    
    yield { "human": human, "window": window}

    #  Teardown    
    goto_default_position(human)

@pytest.mark.parametrize(
    "city, expected_result",
    [
        ("New York", False), 
        ("Berlin", False),
        ("Unknown", True)
    ]
)
def test_city_in_window(setup, city, expected_result):
    """       ."""
    data = setup

    window_view = data["human"].look_into(data["window"])
    recognized_city = data["human"].recognize_city(window_view)
    assert (recognized_city == city) == expected_result, "    "


:



  • setup
  • , ,


, 400+ , .





, 8 setup : , ?



. py.test, .



:



import pytest

class TestWindowView:
    @pytest.fixture
    def setup(self, create_human, goto_room, goto_default_position, choose_window, get_current_view):
        #   
        desired_room = 1 #    ,    
        self.human = create_human("John", "Doe") #          
  
        #  -    ,     
        assert goto_room(self.human, desired_room), "{}     {}".format(human.full_name, desired_room)
    
        #   
        self.window = choose_window(desired_room)
        view = get_current_view(self.window)
        assert view, "  {}  ".format (self.window)
    
        yield

        #  Teardown    
        goto_default_position(self.human)

    @pytest.mark.parametrize(
        "city, expected_result",
        [
            ("New York", False), 
            ("Berlin", False),
            ("Unknown", True)
        ]
    )
    def test_city_in_window(self, setup, city, expected_result):
        """       ."""
        window_view = self.human.look_into(self.window)
        recognized_city = self.human.recognize_city(window_view)
        assert (recognized_city == city) == expected_result, "    "


:



  • global




, .



, . , .



Android/iOS Appium IOT/Embedded .




All Articles