Декораторы параметризации стека pytest с динамическими параметрами

Я новичок в pytest, так что терпите меня.
Я пытаюсь использовать декораторы параметризации стека для проверки нескольких комбинаций перестановок, но вопрос в том, как я могу использовать значения из других декораторов параметризации в стеке.

я обнаружил следующее: но это не совсем то, что я ищу
сложенная параметризация
Использование фикстур в pytest.mark.parametrize \

вот чего я пытаюсь достичь:

@pytest.mark.parametrize("environment", ["main", "develop", "ci"])
@pytest.mark.parametrize("model", get_models())
@pytest.mark.parametrize("id", get_ids(environment, model)) #here i tried to use the returned values of environment and model from the above decorators  
def test_ids(environment, model, id):
    another_method(environment, model, id)
    # some logic here

get_ids() возвращает список идентификаторов на основе заданных environment и model.
это решение не работает, так как оно вызывает неразрешенную ошибку ссылки для environment и model

Причина, по которой я хочу использовать декоратор параметризации, заключается в том, что мне нужно протестировать все перестановки _7 _, _ 8_ и ids, но я хочу, чтобы pytest генерировал отдельный тест для каждой комбинации.

мое текущее решение:

@pytest.mark.parametrize("environment", ["main", "develop", "ci"])
@pytest.mark.parametrize("model", get_models())
def test_ids(environment, model):
    ids = get_ids(environment, model)
    for id in ids:
      another_method(environment, model, id)
      # some logic here

это решение работает, но каждый тест очень длинный, так как он перебирает длинный список идентификаторов, я предпочитаю запускать несколько небольших тестов, а не меньшее количество тестов, но очень долго.
это затрудняет понимание того, что происходит в тестах .
есть предложения?


person Tam Nguyen    schedule 23.02.2021    source источник


Ответы (1)


Есть один способ, которым я могу это сделать, - использовать хуки. Это предполагает использование ловушки pytest_generate_tests, поскольку это позволяет нам параметризовать тесты.

Скрипт test_id я настроил следующим образом.

def get_models():
    return [1,2]

class TestEnvModelIds:
    envs = ["main", "develop", "ci"]
    model = get_models()

    def test_ids(self, environment, model, id):
        pass

Обратите внимание, что мы разместили тест внутри класса, это важно, так как мы хотим получить доступ к этим атрибутам класса позже из нашего хука.

Настоящая магия происходит внутри следующей функции, которую мы помещаем в наш conftest.py в корне нашего тестового каталога. Я создал игрушечные примеры для get_models и get_ids, чтобы проиллюстрировать, что этот подход будет работать. Ваш фактический вариант использования может немного отличаться, так как вам может потребоваться импортировать эти функции из проекта, который вы фактически тестируете.

def get_ids(env, model):
    data = {
        "main": {
            1: ["a", "b"],
            2: ["c", "d"]
        },
        "develop": {
            1: ["e", "f"],
            2: ["g", "h"]
        },
        "ci": {
            1: ["i", "j"],
            2: ["k", "l"]
        }
    }

    return data[env][model]

def pytest_generate_tests(metafunc):
    if "TestEnvModelIds" == metafunc.cls.__qualname__:
        envs = metafunc.cls.envs
        models = metafunc.cls.model
        argnames = metafunc.fixturenames
        argvalues = []
        
        for env in envs:
            for model in models:
                ids = get_ids(env, model)
                for id_ in ids:
                    argvalues.append((env, model, id_))

        metafunc.parametrize(argnames, argvalues, scope="class")

В pytest_generate_tests происходит итерация по средам, затем по моделям и, наконец, по идентификаторам. Мы создаем список этих триплетов и, наконец, параметризуем с ними наш тест.

Когда мы запустим набор тестов с подробным описанием, мы увидим, что успешно сгенерировали все возможные комбинации тестов по желанию.

====================================== test session starts =======================================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /Users/DmitryPolonskiy/Desktop/so/bin/python3.9
cachedir: .pytest_cache
rootdir: ***
collected 12 items                                                                               

tests/test_models.py::TestEnvModelIds::test_ids[main-1-a] PASSED                           [  8%]
tests/test_models.py::TestEnvModelIds::test_ids[main-1-b] PASSED                           [ 16%]
tests/test_models.py::TestEnvModelIds::test_ids[main-2-c] PASSED                           [ 25%]
tests/test_models.py::TestEnvModelIds::test_ids[main-2-d] PASSED                           [ 33%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-1-e] PASSED                        [ 41%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-1-f] PASSED                        [ 50%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-2-g] PASSED                        [ 58%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-2-h] PASSED                        [ 66%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-1-i] PASSED                             [ 75%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-1-j] PASSED                             [ 83%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-2-k] PASSED                             [ 91%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-2-l] PASSED                             [100%]

======================================= 12 passed in 0.04s =======================================
person gold_cy    schedule 24.02.2021
comment
спасибо за ответ, это было действительно полезно, я добавил pytest_generate_tests в свой файл тестового модуля вместо conftest.py, так как у меня есть несколько модулей тестов, и каждый имеет свою собственную уникальную логику параметров, и я не хотел, чтобы мой conftest.py содержал очень большие условия логика - person Tam Nguyen; 28.02.2021
comment
все, что лучше всего подходит для вашего варианта использования, рад, что вы смогли адаптировать ответ в соответствии с вашими конкретными потребностями - person gold_cy; 01.03.2021