pytest中使用命令行选项进行非Python测试

3

我正在使用https://docs.pytest.org/en/latest/example/nonpython.html中的教程实现基于外部文件的自定义测试用例。

我需要以一个布尔标志参数化它们。我希望能够使用命令行选项--use-real-api运行pytest,在我的情况下,它将关闭使用模拟并进行真正的远程网络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")

请问您能更详细地解释一下“参数化”是什么意思吗? - Davide Moro
谢谢您指出这个问题,我已经添加了解释和我的用例。 - adam.ra
1
参考:如果您要在同一项目中拥有自定义的非Python测试和接受命令行参数的传统Python单元测试,则py.test可执行文件将失败 - 这些标准Python测试将抱怨未知的命令行参数(除非您为两个组分别调用pytest)。解决此问题的方法是在test/目录中的顶级中具有一个带有param定义(cmdop fixture和pytest_addoption定义)的conftest.py文件,以及在其子目录中定义自定义非Python逻辑的文件。 - adam.ra
感谢您更新了描述并提供了更多细节!顺便说一下,这有点离题,但在实现pytest中基于非Python的YAML测试之前,您可能需要考虑是否可以重用已经为您完成工作的现有类似插件。例如:https://github.com/pytest-dev/pytest-play - Davide Moro
实际上,这个例子是基于YAML的,因为来自py.test文档的原始示例也是如此。我的实际用例更加复杂——你编写脚本来处理与聊天机器人的预期对话流程,这些脚本是包含用户消息、预期机器人回复以及一些额外的特殊行用于配置和通配符断言的文本文件。我希望将上述情况尽可能简单化,并抽象出我的用例细节。 - adam.ra
1个回答

1

pytest 中的每个集合实体(FileModuleFunction 等)都是 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')
        ...

等等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接