尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

使用 Terratest 为 Azure Storage Account 编写自动化基础设施测试:Terraform Azure Storage 示例深度解析

发布时间:2026/9/27 7:05:51

资讯中心
01
ARTICLE

使用 Terratest 为 Azure Storage Account 编写自动化基础设施测试:Terraform Azure Storage 示例深度解析

使用 Terratest 为 Azure Storage Account 编写自动化基础设施测试:Terraform Azure Storage 示例深度解析
测试开发工具DevOps质量保障【免费下载链接】terratestTerratest is a Go library that makes it easier to write automated tests for your infrastructure code.项目地址https://gitcode.com/gh_mirrors/te/terratest点击查看免费下载本指南以 Terratest 仓库中的examples/azure/terraform-azure-storage-example示例模块为主线讲解如何用 Terraform 在 Azure 上部署一个含 Blob 容器的 Storage Account并借助 Terratest 的 Go 测试库对真实云资源进行自动化断言验证。读完本文你将掌握该示例模块的完整 Terraform 配置、Terratest 测试代码的编写方式、Azure 模块封装函数的底层实现原理以及从环境变量配置到go test运行的完整实战流程。示例模块概览它部署了哪些资源examples/azure/terraform-azure-storage-example/目录下是一个麻雀虽小、五脏俱全的 Terraform 模块。正如其 README 所述该模块向 Azure 部署以下资源用于演示如何用 Terratest 为 Azure 上的 Terraform 代码编写自动化测试Azure Storage Account存储账户对外暴露storage_account_name、storage_account_account_tier层级、storage_account_account_kind类型三个输出变量Azure Storage ContainerBlob 容器对外暴露storage_container_name输出变量支撑上述资源所必需的Resource Group资源组。需要特别说明的是README 明确提示该存储账户本身不承载任何实际业务the Storage Account in this module dont actually do anything它存在的意义纯粹是作为 Terratest 自动化测试的演练目标。因此这个示例非常适合作为学习 Terratest 的入门材料——你可以安全地用它跑通Terraform 部署 → 测试断言 → 销毁清理的完整链路而不必担心破坏真实业务数据。目录结构与文件清单该示例模块共包含 4 个文件职责划分清晰文件职责main.tf声明 azurerm provider 并定义资源组、存储账户、容器三个核心资源variables.tf声明全部输入变量及其默认值同时注释了所需的环境变量outputs.tf将资源的属性暴露为输出供 Terratest 测试读取断言README.md说明模块用途、手动运行步骤与测试运行步骤配套的测试代码位于仓库根目录下的 test/azure/terraform_azure_storage_example_test.go而测试所依赖的 Azure 封装函数位于 modules/azure/storage.go后面会逐一展开。Terraform 模块源码解读main.tf三块资源的串联main.tf 的完整内容如下terraform { required_version 1.0 required_providers { azurerm { source hashicorp/azurerm version ~ 4.0 } } } provider azurerm { features {} } resource azurerm_resource_group resource_group { name terratest-storage-rg-${var.postfix} location var.location } resource azurerm_storage_account storage_account { name storage${var.postfix} resource_group_name azurerm_resource_group.resource_group.name location azurerm_resource_group.resource_group.location account_kind var.storage_account_kind account_tier var.storage_account_tier account_replication_type var.storage_replication_type } resource azurerm_storage_container container { name container1 storage_account_name azurerm_storage_account.storage_account.name container_access_type var.container_access_type }几个值得注意的实现细节Provider 版本约束模块要求 Terraform 版本 1.0并使用hashicorp/azurermprovider 的~ 4.0版本即允许 4.x 范围内的更新不跨大版本。这是当前仓库的实际配置如果你的环境使用更老的 azurerm 版本需要相应调整。命名策略资源组名为terratest-storage-rg-${var.postfix}存储账户名为storage${var.postfix}。由于 Azure 存储账户名要求全局唯一这种前缀 postfix的命名方式正是为了规避命名冲突——测试中会通过random.UniqueID()生成随机后缀注入。资源依赖链存储账户通过resource_group_name和location引用资源组的属性容器通过storage_account_name引用存储账户Terraform 会自动推导依赖顺序完成部署。容器访问类型container_access_type默认为private测试中会专门断言容器没有公共访问权限这是安全性验证的典型用例。variables.tf输入参数与默认值variables.tf 顶部以注释形式列出了测试/部署必须提供的 Azure 凭据环境变量# ARM_CLIENT_ID # ARM_CLIENT_SECRET # ARM_SUBSCRIPTION_ID # ARM_TENANT_ID全部输入变量均为可选参数带有合理默认值汇总如下变量描述类型默认值location存储账户所在区域stringEast USstorage_account_kind存储账户类型KindstringStorageV2storage_account_tier存储账户层级TierstringStandardstorage_replication_type复制类型stringGRScontainer_access_type容器访问类型stringprivatepostfix用于规避资源名冲突的后缀串stringresource从 Azurerm 的语义来看account_kind可选Storage、StorageV2、BlobStorage等account_tier对应Standard或Premiumstorage_replication_type对应LRS、GRS、RAGRS、ZRS等。该示例选择StorageV2 Standard GRS组合属于通用型的默认配置。测试时通常只需覆盖postfix保证唯一性其余沿用默认值即可。outputs.tf测试断言的标尺outputs.tf 暴露了 5 个输出变量output resource_group_name { value azurerm_resource_group.resource_group.name } output storage_account_name { value azurerm_storage_account.storage_account.name } output storage_account_account_tier { value azurerm_storage_account.storage_account.account_tier } output storage_account_account_kind { value azurerm_storage_account.storage_account.account_kind } output storage_container_name { value azurerm_storage_container.container.name }这些输出正是 Terratest 测试的预期值来源测试通过terraform output拿到 Terraform 声称部署的属性再调用 Azure SDK 查询真实资源的实际属性两者比对即可验证 Terraform 配置是否真正生效。手动运行模块按照 README 的指引手动部署该模块的步骤为注册 Azure 账号并完成订阅开通用 Azure CLI 支持的方式配置凭据安装 Terraform 并确保其位于PATH中确保环境变量就绪见下文环境变量与运行前提一节在模块目录执行terraform init初始化 provider执行terraform apply部署资源验证完毕后执行terraform destroy清理资源。环境变量的具体配置清单见 examples/azure/README.md其中ARM_CLIENT_ID、ARM_CLIENT_SECRET、ARM_SUBSCRIPTION_ID、ARM_TENANT_ID四项是 azurerm provider 与 Terratest 共用的标准凭据。对于非商业云环境如 Azure China、US Government还需设置AZURE_ENVIRONMENT环境变量。用 Terratest 编写自动化测试测试代码全解配套测试位于 test/azure/terraform_azure_storage_example_test.go完整代码如下//go:build azure // build azure package test_test import ( fmt strings testing github.com/gruntwork-io/terratest/modules/azure/v2 github.com/gruntwork-io/terratest/modules/core/v2/random github.com/gruntwork-io/terratest/modules/terraform/v2 github.com/stretchr/testify/assert ) func TestTerraformAzureStorageExample(t *testing.T) { t.Parallel() // subscriptionID is overridden by the environment variable ARM_SUBSCRIPTION_ID subscriptionID : uniquePostfix : random.UniqueID() // Configure Terraform setting up a path to Terraform code. terraformOptions : terraform.Options{ // The path to where our Terraform code is located TerraformDir: ../../examples/azure/terraform-azure-storage-example, // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ postfix: strings.ToLower(uniquePostfix), }, } // At the end of the test, run terraform destroy to clean up any resources that were created defer terraform.DestroyContext(t, t.Context(), terraformOptions) // Run terraform init and terraform apply. Fail the test if there are any errors. terraform.InitAndApplyContext(t, t.Context(), terraformOptions) // Run terraform output to get the values of output variables resourceGroupName : terraform.OutputContext(t, t.Context(), terraformOptions, resource_group_name) storageAccountName : terraform.OutputContext(t, t.Context(), terraformOptions, storage_account_name) storageAccountTier : terraform.OutputContext(t, t.Context(), terraformOptions, storage_account_account_tier) storageAccountKind : terraform.OutputContext(t, t.Context(), terraformOptions, storage_account_account_kind) storageBlobContainerName : terraform.OutputContext(t, t.Context(), terraformOptions, storage_container_name) // Verify storage account properties and ensure it matches the output. storageAccountExists : azure.StorageAccountExistsContext(t, t.Context(), storageAccountName, resourceGroupName, subscriptionID) assert.True(t, storageAccountExists, storage account does not exist) containerExists : azure.StorageBlobContainerExistsContext(t, t.Context(), storageBlobContainerName, storageAccountName, resourceGroupName, subscriptionID) assert.True(t, containerExists, storage container does not exist) publicAccess : azure.GetStorageBlobContainerPublicAccessContext(t, t.Context(), storageBlobContainerName, storageAccountName, resourceGroupName, subscriptionID) assert.False(t, publicAccess, storage container has public access) accountKind : azure.GetStorageAccountKindContext(t, t.Context(), storageAccountName, resourceGroupName, subscriptionID) assert.Equal(t, storageAccountKind, accountKind, storage account kind mismatch) skuTier : azure.GetStorageAccountSkuTierContext(t, t.Context(), storageAccountName, resourceGroupName, subscriptionID) assert.Equal(t, storageAccountTier, skuTier, sku tier mismatch) actualDNSString : azure.GetStorageDNSStringContext(t, t.Context(), storageAccountName, resourceGroupName, subscriptionID) storageSuffix, _ : azure.GetStorageURISuffixContextE(t.Context()) expectedDNS : fmt.Sprintf(https://%s.blob.%s/, storageAccountName, storageSuffix) assert.Equal(t, expectedDNS, actualDNSString, Storage DNS string mismatch) }测试的组织方式与关键模式构建标签隔离文件首行//go:build azure表明该测试只在启用azurebuild tag 时参与编译避免无 Azure 凭据的环境误编译。运行示例采用go test -v -run TestTerraformAzureStorageExample配合 tag 即可。并行执行t.Parallel()允许测试与其他 Azure 测试并行运行缩短测试套件整体耗时。随机后缀保证唯一性random.UniqueID()生成唯一后缀经strings.ToLower转小写后作为postfix注入规避 Azure 全局命名冲突。部署-断言-清理三段式terraform.InitAndApplyContext执行terraform init与terraform apply失败即终止测试通过terraform.OutputContext逐一读取 5 个输出变量作为预期值defer terraform.DestroyContext保证无论测试成功与否结束时都会执行terraform destroy清理真实资源避免云资源泄漏与持续计费。断言层真实资源 vs Terraform 输出测试的核心思路是用 Azure SDK 查询真实资源的实际状态与 Terraform 声称的输出值逐一比对断言验证内容StorageAccountExistsContext存储账户在 Azure 上真实存在StorageBlobContainerExistsContext容器真实存在GetStorageBlobContainerPublicAccessContextassert.False容器无公共访问权限与container_access_type private一致GetStorageAccountKindContextassert.Equal真实 Kind 与输出变量storage_account_account_kind一致GetStorageAccountSkuTierContextassert.Equal真实 SKU Tier 与输出变量storage_account_account_tier一致GetStorageDNSStringContextassert.EqualBlob 服务的 DNS 地址与按命名规则推导的https://name.blob.suffix/一致这里体现了 Terratest 相对只看terraform apply是否成功这一弱验证的进阶价值即使 apply 成功真实资源的属性仍可能与配置不符如访问策略被意外修改、SKU 被降级Terratest 通过 SDK 实测来捕获这类漂移。底层原理Azure 模块封装函数测试调用的所有azure.*函数都来自 Terratest 的 modules/azure/storage.go。理解这些封装能让你举一反三地编写自己的 Azure 断言。Context 与 ContextE 双 API 设计该模块遵循 Terratest 的统一约定为每个能力提供两个版本XxxContext(t, ctx, ...)直接接收testing.T出错时调用require.NoError立即失败测试适合在测试体内使用XxxContextE(ctx, ...)返回(结果, error)把错误决策权交给调用方适合需要自定义错误处理的场景。例如StorageAccountExistsContext内部就是调用StorageAccountExistsContextE若返回错误则直接require.NoError(t, err)终止测试func StorageAccountExistsContext(t testing.TestingT, ctx context.Context, storageAccountName string, resourceGroupName string, subscriptionID string) bool { t.Helper() result, err : StorageAccountExistsContextE(ctx, storageAccountName, resourceGroupName, subscriptionID) require.NoError(t, err) return result }资源存在性判定的错误语义StorageAccountExistsContextE与StorageBlobContainerExistsContextE都遵循同一个模式调用查询函数若返回的错误属于资源不存在ResourceNotFoundErrorExists则返回false, nil其他错误才原样返回。这样存在性与查询异常被清晰区分测试逻辑不会把 API 故障误判为资源缺失。订阅与资源组的目标解析在 common.go 中getTargetAzureSubscription与getTargetAzureResourceGroupName处理了一个巧妙的默认逻辑若调用传入空字符串则回退读取环境变量——订阅 ID 读取ARM_SUBSCRIPTION_ID资源组名读取 Terratest 自定义的AZURE_RES_GROUP_NAME。这就是测试代码里subscriptionID : 仍能工作的原因订阅 ID 由ARM_SUBSCRIPTION_ID环境变量提供。若两者皆为空则返回对应的SubscriptionIDNotFound{}/ResourceGroupNameNotFound{}错误。云环境敏感的 URI 后缀测试最后一段调用了GetStorageURISuffixContextE实现在 client_factory.go它会根据当前配置的 Azure 环境返回对应的存储服务域名后缀AzurePublicCloud→core.windows.netAzureUSGovCloud→core.usgovcloudapi.netAzureChinaCloud→core.chinacloudapi.cn环境名取自AZURE_ENVIRONMENT环境变量未设置时默认AzurePublicCloud见getDefaultEnvironmentName。这意味着同样的测试代码在不同云环境政企云、中国区云下都能推导出正确的 Blob 访问地址无需改代码。属性提取的健壮性ExtractStorageAccountKind、ExtractStorageAccountSkuTier、ExtractBlobContainerPublicAccess等提取函数均对 nil 指针做了防护如account nil || account.Kind nil时返回空串/false避免 Azure SDK 返回不完整对象时引发空指针 panic这也是编写健壮云测试的重要技巧。环境变量与运行前提结合 examples/azure/README.md 的说明运行该示例的完整前提如下Linux/macOS 下的凭据配置export ARM_CLIENT_IDyour_app_id export ARM_CLIENT_SECRETyour_password export ARM_SUBSCRIPTION_IDyour_subscription_id export ARM_TENANT_IDyour_tenant_id # 非必需默认 AzurePublicCloud。按需选择 # export AZURE_ENVIRONMENTAzureUSGovernmentCloud # export AZURE_ENVIRONMENTAzureChinaCloud # export AZURE_ENVIRONMENTAzureGermanCloud # export AZURE_ENVIRONMENTAzurePublicCloud # export AZURE_ENVIRONMENTAzureStackCloudWindows 下需以系统环境变量方式设置可在管理员 PowerShell 中执行[System.Environment]::SetEnvironmentVariable(ARM_CLIENT_ID,$your_app_id,[System.EnvironmentTarget]::Machine) [System.Environment]::SetEnvironmentVariable(ARM_CLIENT_SECRET,$your_password,[System.EnvironmentTarget]::Machine) [System.Environment]::SetEnvironmentVariable(ARM_SUBSCRIPTION_ID,$your_subscription_id,[System.EnvironmentTarget]::Machine) [System.Environment]::SetEnvironmentVariable(ARM_TENANT_ID,$your_tenant_id,[System.EnvironmentTarget]::Machine) [System.Environment]::SetEnvironmentVariable(AZURE_ENVIRONMENT,$your_azure_env,[System.EnvironmentTarget]::Machine)此外还需安装 Go 工具链并保证仓库代码位于可访问路径下。modules 均以github.com/gruntwork-io/terratest/modules/.../v2的形式引入go build/go test会自动拉取依赖。运行测试从命令行到结果验证按 README 的指引运行自动化测试的步骤为完成上述 Azure 凭据与环境变量配置进入测试目录cd test/azure先编译验证go build terraform_azure_storage_example_test.go运行目标测试go test -v -run TestTerraformAzureStorageExample配合azurebuild tag。运行过程中 Terratest 会依序完成terraform init→terraform apply部署真实资源 →terraform output读取输出 → Azure SDK 查询真实属性并断言 →terraform destroy清理。-v标志会输出每个断言步骤的详细日志若有断言失败testify 会给出明确的失败消息如 storage account kind mismatch便于快速定位是配置漂移还是预期值有误。成本与安全注意事项README 给出了明确的成本警告在仓库或云环境中复跑该示例时必须留意该模块会向你的 Azure 订阅部署真实资源产生真实计费模块所用资源均属于Azure Free Account 免费额度范围若免费额度尚未耗尽理论上不会产生费用但所有 Azure 费用完全由使用者自行承担建议在测试前后通过terraform destroy与 Azure 门户核查资源是否已清理。此外该测试被//go:build azure标签隔离且默认不运行需显式指定 tag这也是一种默认安全的设计——避免开发者在没有云凭据的环境中误触发真实资源的部署。小结通过这个示例可以完整看到 Terratest 在 Azure 场景下的最佳实践闭环Terraform 模块定义期望状态 → 输出变量作为断言标尺 → Terratest 测试执行部署 → Azure SDK 实测真实属性 → 断言比对 → 自动销毁清理。在此基础上你可以按照同样的模式扩展出自己的 Azure 测试参照 modules/azure 中已有的封装为其他资源如 AKS、Cosmos DB、Key Vault 等编写断言复用random.UniqueID()、terraform.Options、DestroyContext等模式保证测试的可重复性与清理可靠性借助ContextE系列函数在自定义错误处理场景下复用相同的能力。如果想进一步探索仓库中还有大量同类 Azure 示例examples/azure/下的其他terraform-azure-*-example目录其测试文件、示例 README 与 modules/azure 源码构成了一个可系统化学习的 Azure 基础设施测试素材库。赞分享测试开发工具DevOps质量保障【免费下载链接】terratestTerratest is a Go library that makes it easier to write automated tests for your infrastructure code.项目地址https://gitcode.com/gh_mirrors/te/terratest点击查看免费下载相关推荐FriendOmi后端每日负面反馈报告Daily Negative-Feedback Report架构与运维实践FriendOmi后端每日负面反馈报告Daily Negative Feedback Report架构与运维实践 导读 本文围绕 Friend 仓库项测试开发工具DevOps质量保障使用 Terratest 为 Azure Synapse Analytics Terraform 模块编写自动化测试使用 Terratest 为 Azure Synapse Analytics Terraform 模块编写自动化测试 本指南以仓库中的 terraform az测试开发工具DevOps质量保障escrcpy 远程设备隧道连接完全指南远程 ADB 服务器与 SSH 隧道实战escrcpy 远程设备隧道连接完全指南远程 ADB 服务器与 SSH 隧道实战 本指南基于 escrcpy 仓库中的 tunnels.md https://测试开发工具DevOps质量保障上一篇【亲测免费】 推荐一款智能家居神器Xgimi-4-Home-Assistant下一篇怎样高效管理Kubernetes镜像Argo CD Image Updater智能更新策略全面解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。