Passer des objets dynamiques de la configuration à la fonction de test dans py.test

Dans les grands projets, à un moment donné, une situation se produit alors qu'il y a déjà beaucoup de tests sur le projet et qu'en parallèle, son propre cadre de haut niveau se développe. Le cadre, dans ce cas, en tant que wrapper sur les fonctions de l'objet de test et les capacités de divers outils utilisés dans le projet. De plus, tous les dossiers sont remplis de fixtures, dont beaucoup sont utilisées dans un seul fichier de test.



En ce moment merveilleux, certains problèmes surgissent. J'ai déjà écrit sur l'un d'eux, il s'agit de la mise en œuvre d'un paramétrage pratique, par exemple à partir d'un fichier . Nous parlerons du prochain des plus malheureux dans cet article.



"Capitaine, nous avons beaucoup de rencontres et des globaux apparaissent."



La surcharge des répertoires de test avec des fixtures est une conséquence tout à fait logique de l'utilisation du concept qui est intégré dans py.test, mais parfois cette approche va au-delà de l'acceptable. De plus, nous pouvons souvent observer des constructions dans les tests, qui sont conçues pour déterminer quelles informations un test doit prendre dans un cas particulier particulier, ou une volonté de vérifier dans un premier temps la possibilité de passer le test plus avant au stade de la préparation de l'environnement.



La plus grande idée fausse, dans une situation où ces constructions sont passées à partir d'un setupappareil et vont tout au long du test, est d'utiliser des globalvariables. J'ai été confronté à des cas difficiles similaires et cette idée est l'une des premières à me venir à l'esprit.



Il convient de mentionner à ce stade que le concept de luminaires évite cette tache de propreté du code, mais fournit également des niveaux supplémentaires d'abstraction et de nombreuses références. En dernier recours, vous pouvez prendre une terrible habitude de déballer le résultat d'un appareil, mais dans ce cas, nous gâchons les journaux, car nous n'avons pas de division en configuration, exécution et démontage, et nous compliquons en outre le code au moment du déballage des résultats ou produisons plusieurs raccourcis.



Regardons quelques exemples et commençons par le pire:



"Fixtures et 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, "    "


Par conséquent:



  • Il y a des vérifications initiales
  • Il y a un malheureux 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