Непиратоновые тесты с опцией командной строки в pytest - PullRequest
3 голосов
/ 01 июля 2019

Я реализую пользовательские тестовые случаи, основанные на внешних файлах, используя учебник из https://docs.pytest.org/en/latest/example/nonpython.html.

Мне нужно параметризировать их одним флагом bool. Я хотел бы иметь возможность запускать pytest с параметром командной строки, в моем случае --use-real-api, который отключает использование mocks и реально взаимодействует с API удаленной сети.

Я попытался использовать учебник cmdopt и смешать их вместе, но не могу найти способ прочитать параметр из пользовательского подкласса pytest.Item. Не могли бы вы помочь? Вот тривиальный пример из учебника. Я хотел бы, чтобы это изменило поведение теста в зависимости от значения пройденного cmdopt.

# content of conftest.py
import pytest


def pytest_collect_file(parent, path):
    if path.ext == ".yml" and path.basename.startswith("test"):
        return YamlFile(path, parent)


class YamlFile(pytest.File):
    def collect(self):
        import yaml
        raw = yaml.safe_load(self.fspath.open())
        for name, spec in sorted(raw.items()):
            yield YamlItem(name, self, spec)


class YamlItem(pytest.Item):
    def __init__(self, name, parent, spec):
        super().__init__(name, parent)
        self.spec = spec

    def runtest(self):
        for name, value in sorted(self.spec.items()):
            # some custom test execution (dumb example follows)
            if name != value:
                raise YamlException(self, name, value)

    def repr_failure(self, excinfo):
        """ called when self.runtest() raises an exception. """
        if isinstance(excinfo.value, YamlException):
            return "\n".join(
                [
                    "usecase execution failed",
                    "   spec failed: %r: %r" % excinfo.value.args[1:3],
                    "   no further details known at this point.",
                ]
            )

    def reportinfo(self):
        return self.fspath, 0, "usecase: %s" % self.name


class YamlException(Exception):
    """ custom exception for error reporting. """


def pytest_addoption(parser):
    parser.addoption(
        "--cmdopt", action="store", default="type1", help="my option: type1 or type2"
    )


@pytest.fixture
def cmdopt(request):
    return request.config.getoption("--cmdopt")

1 Ответ

1 голос
/ 01 июля 2019

Каждая сущность коллекции в pytest (File, Module, Function и т. Д.) Является подтипом класса Node, который определяет доступ к объекту config.Зная это, задача становится легкой:

def pytest_addoption(parser):
    parser.addoption('--run-yml', action='store_true')

def pytest_collect_file(parent, path):
    run_yml = parent.config.getoption('--run-yml')
    if run_yml and path.ext == ".yml" and path.basename.startswith("test"):
        return YamlFile(path, parent)

Запуск pytest --run-yml теперь будет собирать файлы YAML;без флага они игнорируются.

То же самое для доступа к конфигурации в пользовательских классах, например:

class YamlItem(pytest.Item):    
    def runtest(self):
        run_yml = self.config.getoption('--run-yml')
        ...

и т. д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...