Passando objetos dinâmicos da configuração para a função de teste em py.test

Em grandes projetos, em algum ponto, ocorre uma situação em que já existem muitos testes no projeto e em paralelo seu próprio framework de alto nível está sendo desenvolvido. A estrutura, neste caso, como um invólucro sobre as funções do objeto de teste e os recursos de várias ferramentas que são usadas no projeto. Além disso, todas as pastas são preenchidas com acessórios, muitos dos quais são usados ​​apenas em um arquivo de teste.



Neste momento maravilhoso, surgem alguns problemas. Já escrevi sobre um deles, esta é a implementação de parametrização conveniente, por exemplo, a partir de um arquivo . Falaremos sobre o próximo dos mais infelizes neste artigo.



"Capitão, temos muitos acessórios e globais aparecem"



Sobrecarregar os diretórios de teste com fixtures é uma consequência lógica do uso do conceito incluído em py.test, mas às vezes essa abordagem vai além do aceitável. Além disso, muitas vezes podemos observar construções em testes, que são projetadas para determinar quais informações um teste precisa levar em um caso específico, ou o desejo de verificar inicialmente a possibilidade de passar ainda mais no teste na fase de preparação do ambiente.



O maior equívoco, em uma situação em que essas construções são passadas de algum setupdispositivo e passam por todo o teste, é usar globalvariáveis. Já enfrentei casos difíceis semelhantes e essa ideia é uma das primeiras que me vêm à mente.



Vale a pena mencionar neste ponto que o conceito de fixtures evita essa mancha de limpeza do código, mas também fornece níveis adicionais de abstração e muitas referências. Como último recurso, você pode adquirir o péssimo hábito de desempacotar o resultado de uma luminária, mas neste caso, estragamos os logs, porque não temos uma divisão em Setup, Run e Teardown e, além disso, complicamos o código no momento de desempacotar os resultados ou produzir vários atalhos.



Vejamos alguns exemplos e comece com o pior:



"Jogos e 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 um resultado:



  • Existem verificações iniciais
  • Há um malfadado 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