跳转到主要内容

pytest插件,用于使用terraform fixtures进行基础设施的单元/功能测试

项目描述

简介

CI codecov

pytest_terraform是一个pytest插件,它允许通过fixture将terraform用于在单元/功能测试中提供基础设施。

此插件使用fixture工厂模式,通过装饰器实现fixture的参数化构造。

使用方法

pytest_terraform提供了一个具有以下参数的terraform装饰器

参数 必需? 类型 默认值 描述
terraform_dir String 要执行的Terraform模块(目录)。
scope String "function" Pytest范围 - 应为: functionsession。其他范围如 classmodulepackage 应该可以工作,但尚未完全测试。
replay 布尔值 True 使用记录的资源而不是调用terraform。有关更多详细信息,请参阅 Replay支持
name String None 用于fixture的名称。如果没有提供,则默认为terraform_dir
teardown String "default" 配置用于 Terraform 资源拆解的模式。有关详细信息,请参阅拆解选项

示例

from boto3 import Session
from pytest_terraform import terraform


# We use the terraform decorator to create a fixture with the name of
# the terraform module.
#
# The test function will be invoked after the terraform module is provisioned
# with the results of the provisioning.
#
# The module `aws_sqs` will be searched for in several directories, the test
# file directory, a sub directory `terraform`.
#
# This fixture specifies a session scope and will be run once per test run.
#
@terraform('aws_sqs', scope='session')
def test_sqs(aws_sqs):
    # A test is passed a terraform resources class containing content from
    # the terraform state file.
    #
    # Note the state file contents may vary across terraform versions.
    #
    # We can access nested datastructures with a jmespath expression.
    assert aws_sqs["aws_sqs_queue.test_queue.tags"] == {
        "Environment": "production"
    }
   queue_url = aws_sqs['test_queue.queue_url']
   print(queue_url)


def test_sqs_deliver(aws_sqs):
   # Once a fixture has been defined with a decorator
   # it can be reused in the same module by name, with provisioning
   # respecting scopes.
   #
   sqs = Session().client('sqs')
   sqs.send_message(
       QueueUrl=aws_sqs['test_queue.queue_url'],
       MessageBody=b"123")


@terraform('aws_sqs')
def test_sqs_dlq(aws_sqs):
   # the fixture can also referenced again via decorator, if redefined
   # with decorator the fixture parameters much match (ie same session scope).

   # Module outputs are available as a separate mapping.
   aws_sqs.outputs['QueueUrl']

注意 固件名称应与 Terraform 模块名称匹配

注意 Terraform 状态文件被认为是 Terraform 的内部实现细节,并非版本间的稳定公共接口。

标记

所有使用 Terraform 固件的测试都应用了 terraform 标记,因此可以通过命令行运行/选择它们,例如。

pytest -k terraform tests/

仅运行所有 Terraform 测试。有关更多详细信息,请参阅 pytest 标记文档,https://pytest.cn/en/stable/example/markers.html#mark-examples

选项

您可以提供 Terraform 二进制文件的路径,否则它会自动发现

--tf-binary=$HOME/bin/terraform

固件引用的 Terraform 模块将在几个不同的位置查找,直接在测试模块的同一目录中,在名为 terraform 的子目录中,以及在名为 terraform 的兄弟目录中。可以给出一个显式的目录,它将首先用于所有模块。

--tf-mod-dir=terraform

此插件还支持飞行记录(请参阅下一节)

--tf-replay=[record|replay|disable]

拆解选项

pytest_terraform 支持 Terraform 装饰器的三种不同拆解模式。默认情况下,pytest_terraform.teardown.ON 将始终尝试通过 terraform destory 拆解任何模块。如果销毁失败,它将引发异常以通知测试运行器。下一个模式是 pytest_terraform.teardown.IGNORE,它将像 teardown.ON 一样调用 terraform destroy,但会忽略任何失败。此模式特别有助于您的测试函数对由 Terraform 模块创建的对象执行破坏性操作。最后一个选项是 pytest_terraform.teardown.OFF,它将完全删除拆解方法。这通常只在非常特定的情况下使用,并被视为边缘情况。

有一个特殊的 pytest_terraform.teardown.DEFAULT,这是 teardown 参数的实际默认值。

拆解选项可以在 Terraform 装饰器上方便地使用。例如,将拆解设置为忽略

from pytest_terraform import terraform


@terraform('aws_sqs', teardown=terraform.TEARDOWN_IGNORE)
def test_sqs(aws_sqs):
    assert aws_sqs["aws_sqs_queue.test_queue.tags"] == {
        "Environment": "production"
    }
   queue_url = aws_sqs['test_queue.queue_url']
   print(queue_url)

钩子

pytest_terraform 通过 pytest 钩子实现提供钩子。钩子应添加到 conftest.py 文件中。

pytest_terraform_modify_state

此钩子在从 Terraform apply 捕获状态后执行,并在写入磁盘之前。此钩子不修改传递给测试函数的状态。状态作为具有以下方法和属性的 TerraformStateJson UserString 类的 tfstate 关键字参数传递:

  • TerraformStateJson.dict - 反序列化状态作为字典
  • TerraformStateJson.update(state: str) - 用新的状态字符串替换序列化的状态
  • TerraformStateJson.update_dict(state: dict) - 用字典替换序列化的状态

示例

def pytest_terraform_modify_state(tfstate):
    print(str(tfstate))

示例 AWS 账户清除

import re

def pytest_terraform_modify_state(tfstate):
    """ Replace potential AWS account numbers with 'REDACTED' """
    tfstate.update(re.sub(r'([0-9]+){12}', 'REDACTED', str(tfstate)))

飞行记录

此插件的使用/哲学基于使用飞行记录对云基础设施进行单元测试。在飞行记录中,而不是模拟或存根基础设施,实际资源被创建并与它们交互,记录响应,然后重放这些响应以快速执行测试。除了提供的精确度外,这也允许这些测试在实时基础设施上执行/重录,以进行额外的功能/发布测试。

https://cloudcustodian.io/docs/developer/tests.html#creating-cloud-resources-with-terraform

重放支持

默认情况下,固件将 tf_resources.json 保存回模块目录,在重放模式下使用。

可以通过在命令行上传递 --tf-replay 或通过 pytest 配置文件配置重放。

记录

通过传递固件参数 replay 可以控制单个测试的重放行为。默认情况下,在记录模式下操作。

@terraform('file_example', replay=False) def test_file_example(file_example): assert file_example['local_file.bar.content'] == 'bar!'

XDist 兼容性

pytest_terraform 支持在多进程(非分布式)模式下使用 pytest-xdist。

当与 python-xdist 一起运行时,pytest_terraform 将所有非功能范围视为每个测试运行的工作固定作用域,尊重其原始作用域生命周期,但具有全局语义,而不是每个工作进程一次(xdist 默认)。

为此,插件使用锁文件、测试执行日志和固定作用域到测试的依赖映射来进行多进程协调。任何工作进程都可以在执行完依赖于给定固定作用域的最后一个测试后执行模块拆解。所有供应和拆解都受到 pytest 执行临时目录中原子文件锁的保护。

根模块引用

terraform_remote_state 可以用于在单个测试中引入范围根模块之间的依赖关系,注意我们不是试图支持相同作用域的固定作用域之间的依赖关系,因为这会在 pytest 原生能力之外施加额外的调度约束。更高作用域的根模块(即会话或模块作用域)需要输出变量才能启用此消费。

项目详细信息


下载文件

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

源分布

pytest_terraform-0.7.0.tar.gz (16.5 kB 查看哈希值)

上传时间

构建分布

pytest_terraform-0.7.0-py3-none-any.whl (16.7 kB 查看哈希值)

上传时间 Python 3

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面