Pasar objetos dinámicos de la configuración a la función de prueba en py.test

En proyectos grandes, en algún momento, se da una situación en la que ya hay muchas pruebas en el proyecto y, en paralelo, se está desarrollando su propio marco de alto nivel. El marco, en este caso, como un envoltorio sobre las funciones del objeto de prueba y las capacidades de varias herramientas que se utilizan en el proyecto. Además, todas las carpetas están llenas de accesorios, muchos de los cuales solo se utilizan en un archivo de prueba.



En este maravilloso momento surgen algunos problemas. Ya escribí sobre uno de ellos, esta es la implementación de una parametrización conveniente, por ejemplo, desde un archivo . Hablaremos del siguiente de los más desafortunados en este artículo.



"Capitán, tenemos muchos accesorios y aparecen globales".



La sobrecarga de directorios de prueba con accesorios es una consecuencia bastante lógica de usar el concepto que se incluye en py.test, pero a veces este enfoque va más allá de lo aceptable. Además, a menudo podemos observar construcciones en las pruebas, que están diseñadas para determinar qué información debe tomar una prueba en un caso específico particular, o el deseo de verificar inicialmente la posibilidad de pasar la prueba en la etapa de preparación del entorno.



El error más grande, en una situación en la que estas construcciones se pasan de algún setupdispositivo y siguen toda la prueba, es usar globalvariables. Me he enfrentado a casos difíciles similares y esta idea es una de las primeras que me viene a la mente.



Vale la pena mencionar en este punto que el concepto de accesorios evita esta mancha de limpieza del código, pero también proporciona niveles adicionales de abstracción y muchas referencias. Como último recurso, puede adquirir el terrible hábito de desempacar el resultado de un accesorio, pero en este caso, estropeamos los registros, porque no tenemos una división en Setup, Run y ​​Teardown, y adicionalmente complicamos el código al momento de desempaquetar los resultados o producir múltiples atajos.



Veamos algunos ejemplos y comencemos con el peor:



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


Como resultado:



  • Hay controles iniciales
  • Hay un desafortunado 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