跳转到主要内容

A py.test插件,提供配置以简化inmanta模块测试。

项目描述

pytest-inmanta

用于测试inmanta模块的pytest插件

安装

pip install pytest-inmanta

如果您想使用pytest-inmanta测试v2模块,请确保安装该模块

inmanta module install -e .

用法

此插件提供了一个测试夹具,可以编译、导出和部署代码,而无需运行实际的inmanta服务器。

def test_compile(project):
    """
        Test compiling a simple model that uses std
    """
    project.compile("""
host = std::Host(name="server", os=std::linux)
file = std::ConfigFile(host=host, path="/tmp/test", content="1234")
        """)

夹具还提供了对模型内部结构的访问

    assert len(project.get_instances("std::Host")) == 1
    assert project.get_instances("std::Host")[0].name == "server"

对导出资源的访问

    f = project.get_resource("std::ConfigFile")
    assert f.permissions == 644

对编译输出和模拟文件系统的访问

def test_template(project):
    """
        Test the evaluation of a template
    """
    project.add_mock_file("templates", "test.tmpl", "{{ value }}")
    project.compile("""import unittest
value = "1234"
std::print(std::template("unittest/test.tmpl"))
    """)

    assert project.get_stdout() == "1234\n"

并允许部署特定资源

    # perform deploy
    result = project.deploy_resource_v2("std::ConfigFile", expected_status=inmanta.const.ResourceState.deployed)
    # assert the deploy performed no changes
    result.assert_no_changes()
    # assert the deploy produced specific log lines
    result.assert_has_logline("Calling read_resource")

和干运行

    result = project.dryrun_resource_v2("testmodule::Resource")
    assert result.changes == {"value": {'current': 'read', 'desired': 'write'}}
    # Or dryrun all resources at once
    result = project.dryrun_all()

也可以一次性部署所有资源

    results = project.deploy_all()
    assert results.get_context_for("std::ConfigFile", path="/tmp/test").status == ResourceState.deployed

dryrun_alldeploy_all函数返回一个包含一些有用的辅助函数以进行一些基本检查的Result对象。

我们可以检查结果中每个资源是否具有正确的状态

    results = project.dryrun_all()
    results.assert_all(ResourceState.dry)

可以确定每个资源在其更改中是否都有purged属性。这有助于断言资源是否将被创建(purged设置为True)或删除(purged设置为False)

    results = project.dryrun_all()
    results.assert_resources_have_purged()

相同的情况也适用于deploy_all

    results = project.deploy_all()
    results.assert_all(ResourceState.deployed)

要检查部署是否成功并且我们达到了期望的状态,可以在部署后进行干运行并检查是否有更改

    results = project.deploy_all()
    results.assert_all(ResourceState.deployed)

    results = project.dryrun_all()
    results.assert_has_no_changes()

为了方便,也可以一次性进行干运行和部署所有资源。此方法还断言干运行和部署通过上述基本检查。它返回一个DeployResultCollection,该集合汇总了干运行和部署的Results

    resutls = project.dryrun_and_deploy_all(assert_create_or_delete=True)
    results.first_dryrun.assert_all(ResourceState.dry)
    results.deploy.assert_all(ResourceState.deployed)
    results.last_dryrun.assert_all(ResourceState.dry)

使用inmanta_plugins夹具测试v1模块中定义的函数和类也是可能的。夹具将inmanta模块作为其属性公开,并在访问时动态导入它们。对于v2模块,建议的方法是只使用顶层导入而不是使用夹具。

    def test_example(inmanta_plugins):
        inmanta_plugins.testmodule.regular_function("example")

这种动态性是必需的,因为编译器在调用project.compile时重置模块导入。因此,如果您将模块存储在局部变量中,它将不会在编译过程中幸存。因此,建议您以完全限定方式(使用夹具)访问inmanta_plugins包中的模块。以下示例演示了这一点。

    def test_module_inequality(project, inmanta_plugins):
        cached_module = inmanta_plugins.testmodule
        assert cached_module is inmanta_plugins.testmodule

        project.compile("import testmodule")

        assert cached_module is not inmanta_plugins.testmodule

虽然您可以直接从inmanta_plugins包导入,但夹具对模块重新加载进行了抽象。如果没有夹具,您将需要在project.compile之后重新导入。

测试插件

以下插件为例

    # <module-name>/plugins/__init__.py

    from inmanta.plugins import plugin

    @plugin
    def hostname(fqdn: "string") -> "string":
        """
            Return the hostname part of the fqdn
        """
        return fqdn.split(".")[0]

一个测试用例,用于测试此插件,看起来像这样

    # <module-name>/tests/test_hostname.py

    def test_hostname(project):
        host = "test"
        fqdn = f"{host}.something.com"
        assert project.get_plugin_function("hostname")(fqdn) == host
  • 第3行:创建一个pytest测试用例,该测试用例需要project夹具。
  • 第6行:调用函数project.get_plugin_function(plugin_name: str): FunctionType,该函数返回名为plugin_name的插件函数。因此,此行测试当使用参数fqdn调用插件函数hostname时是否返回host

高级用法

由于pytest-inmanta保留inmanta_plugins子模块对象以支持顶层导入,任何有状态模块(在模块命名空间中保持状态的全局Python变量)必须定义清理逻辑以在编译之间重置状态。pytest-inmanta期望这样的清理函数是同步函数,位于inmanta_plugins子模块(任何深度)的顶层作用域(定义在模块对象上,而不是在类中)。它们的名称应以"inmanta_reset_state"开头,并且不应接受任何参数。例如

    # <module-name>/plugins/state.py

    MY_STATE = set()

    def inmanta_reset_state() -> None:
        global MY_STATE
        MY_STATE = set()

可以定义多个清理函数,在这种情况下,没有定义保证的调用顺序。

选项

以下选项可用。

  • --venv:放置测试虚拟环境的文件夹(将由所有测试共享),覆盖INMANTA_TEST_ENV。此选项依赖于符号链接支持。此选项在所有Windows版本上均不起作用。在Windows 10上,您需要在管理员外壳中运行pytest。使用固定的虚拟环境可以加快测试的运行速度。
  • --pip-index-url:指定从哪里安装依赖项的pip索引。可以多次指定以添加多个索引。当设置时,即使设置了pip-use-system-config,也会覆盖系统索引-url。(覆盖PIP_INDEX_URL,默认为[]
  • --pip-pre--no-pip-pre 允许pip安装预发布包吗?(覆盖PIP_PRE,默认为--install-mode != release
  • --pip-use-system-config 允许pytest-inmanta使用系统pip配置吗?(覆盖INMANTA_PIP_USE_SYSTEM_CONFIG,默认为False
  • --use-module-in-place:使得inmanta将你的模块目录的父目录添加到其目录路径中,而不是将你的模块复制到临时libs目录。这允许你对特定版本的依赖模块进行测试。使用此选项可以提高测试速度,因为模块依赖项不会多次下载。
  • --module-repo:从哪里下载v1模块的位置,覆盖INMANTA_MODULE_REPO。默认值是inmanta的github组织。可以通过空格分隔它们或通过多次传递参数来传递多个仓库。
  • --install-mode:在这次测试期间下载的v1模块要使用的安装模式,覆盖INMANTA_INSTALL_MODE
  • --no-load-plugins:不要在Project类中加载插件。覆盖INMANTA_NO_LOAD_PLUGINS。当在测试插件时,如果不使用此选项,在project.get_plugin_function方法中,模块的plugin/__init__.py可能会被加载多次,这可能导致在具有副作用的情况下出现问题,因为它们也会多次执行。
  • --no-strict-deps-check:选项以对要求使用传统的检查(更宽松)来运行pytest-inmanta。默认情况下将使用新的严格检查。

使用通用的pytest选项--log-cli-level来显示Inmanta日志器以查看任何设置或清理警告。例如,--log-cli-level=INFO

与pytest-cov兼容性

当pytest-inmanta与pytest-cov pytest插件一起使用时,应设置--use-module-in-place选项。如果没有设置此选项,报告的测试覆盖率将是不正确的。

使用pytest选项框架

pytest-inmanta扩展包含一个框架,可以帮助创建在测试套件或测试扩展中使用的pytest选项。

每个选项都可以通过CLI参数或环境变量设置。如果两者都设置,则CLI参数值优先于环境变量。

在创建新选项时,请注意将其放置在pytest始终会加载的位置,例如conftest.py文件。

此处显示可以使用的不同类型测试参数:pytest_inmanta/test_parameters。目前支持的类型包括

当然,您可以添加并使用自己的选项类型,只要它正确地扩展了基类TestParameter

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

pytest_inmanta-3.0.0.tar.gz (46.5 kB 查看哈希值)

上传时间:

支持者