4. 测试环境搭建:使用 Terratest、Go 语言环境、AWS/GCP/Azure Provider 模拟器配置
搭建可复现、隔离且低成本的测试环境是模块测试策略的基石。本章将指导你完成三部分核心环境的配置:Go 语言与 Terratest 框架、云 Provider 模拟器(LocalStack / FakeGCS / Azurite),以及测试项目结构的初始化。通过模拟器,你可以在本地运行测试,无需真实云资源,从而大幅提升测试速度与安全性。
4.1 环境全景:测试栈组件与关系
下图展示了测试执行时各组件之间的调用关系与数据流。Terratest 作为测试框架,通过 Go 测试函数调用云 SDK 或 HTTP API,与运行在本地的 Provider 模拟器交互,模拟真实云服务的资源生命周期。
4.2 Go 语言环境与 Terratest 安装
Terratest 是一个基于 Go 的测试库,专门用于基础设施代码的自动化测试。它提供了一组帮助函数,用于执行 Terraform 命令、验证云资源状态以及处理 HTTP 响应。
4.2.1 安装 Go 与配置工作区
- 下载 Go:访问
go.dev/dl,选择对应操作系统的版本(推荐 1.21+)。 - 设置环境变量:确保
GOPATH和GOROOT正确配置,并将$GOPATH/bin加入PATH。 - 验证安装:运行
go version确认输出。
go mod init github.com/your-org/terraform-module-tests 初始化模块。
4.2.2 安装 Terratest
在测试目录下执行以下命令,将 Terratest 添加为依赖:
cd test
go get github.com/gruntwork-io/terratest/modules/terraform
go get github.com/gruntwork-io/terratest/modules/aws
go get github.com/gruntwork-io/terratest/modules/http-helper
Terratest 的核心包功能如下表所示:
| 包路径 | 核心功能 | 典型使用场景 |
|---|---|---|
modules/terraform |
执行 init、apply、destroy、output | 部署与销毁测试环境 |
modules/aws |
封装 AWS SDK 调用(S3、EC2、IAM) | 验证 AWS 资源状态 |
modules/http-helper |
发送 HTTP 请求并断言响应 | 测试 API Gateway / ALB 端点 |
modules/files |
文件与目录操作 | 复制 Terraform 配置到临时目录 |
modules/logger |
结构化日志输出 | 调试测试执行过程 |
4.3 Provider 模拟器配置
模拟器允许你在本地模拟云服务 API,避免真实资源费用和网络延迟。以下分别介绍 AWS、GCP、Azure 三种模拟器的配置方法。
4.3.1 LocalStack(AWS 模拟器)
LocalStack 是最成熟的 AWS 模拟器,支持 S3、DynamoDB、Lambda、EC2 等核心服务。使用 Docker Compose 启动:
# docker-compose.yml
version: "3.8"
services:
localstack:
image: localstack/localstack:latest
ports:
- "4566:4566" # 主网关端口
environment:
- SERVICES=s3,iam,ec2 # 按需启用服务
- AWS_DEFAULT_REGION=us-east-1
- EDGE_PORT=4566
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
启动后,在 Terratest 测试中配置 AWS endpoint:
awsSession := aws.NewSession(t, &aws.Config{
Region: aws.String("us-east-1"),
Endpoint: aws.String("http://localhost:4566"),
Credentials: credentials.NewStaticCredentials("fake", "fake", ""),
S3ForcePathStyle: aws.Bool(true),
})
S3ForcePathStyle,否则路径解析会出错。IAM 策略模拟存在部分限制,复杂策略建议在真实环境验证。
4.3.2 FakeGCS(GCP Storage 模拟器)
FakeGCS 是一个轻量级的 GCS 模拟器,支持 Bucket 创建、对象上传/下载。使用 Docker 运行:
docker run -d --name fake-gcs \
-p 4443:4443 \
-v /tmp/fake-gcs-data:/data \
fsouza/fake-gcs-server:latest
在 Terratest 中,通过设置 STORAGE_EMULATOR_HOST 环境变量或直接使用自定义 HTTP 客户端来访问:
os.Setenv("STORAGE_EMULATOR_HOST", "http://localhost:4443")
// 之后使用标准 GCP SDK 即可自动指向模拟器
4.3.3 Azurite(Azure 模拟器)
Azurite 是 Azure 存储服务的官方模拟器,支持 Blob、Queue 和 Table。使用 npm 或 Docker 安装:
# 使用 Docker
docker run -d --name azurite \
-p 10000:10000 \
-p 10001:10001 \
-p 10002:10002 \
mcr.microsoft.com/azure-storage/azurite
端口映射说明:
| 端口 | 服务 | 连接字符串示例 |
|---|---|---|
| 10000 | Blob 服务 | DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1; |
| 10001 | Queue 服务 | 同上,替换 QueueEndpoint |
| 10002 | Table 服务 | 同上,替换 TableEndpoint |
4.4 测试项目结构初始化
一个标准的 Terraform 模块测试项目结构如下:
terraform-module/
├── main.tf # 模块主入口
├── variables.tf # 输入变量
├── outputs.tf # 输出值
├── test/
│ ├── go.mod # Go 模块定义
│ ├── go.sum # 依赖锁文件
│ ├── basic_test.go # 基础功能测试
│ ├── policy_test.go # 策略合规测试
│ └── fixtures/
│ ├── basic/ # 测试用例的 Terraform 配置
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ └── policy/
│ ├── main.tf
│ └── terraform.tfvars
└── Makefile # 统一命令入口
4.4.1 编写第一个测试文件
以下是一个使用 LocalStack 模拟器的完整测试示例:
// test/basic_test.go
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/stretchr/testify/assert"
)
func TestS3BucketCreation(t *testing.T) {
t.Parallel()
terraformOptions := &terraform.Options{
TerraformDir: "../fixtures/basic",
Vars: map[string]interface{}{
"bucket_name": "test-bucket-001",
"region": "us-east-1",
},
EnvVars: map[string]string{
"AWS_ACCESS_KEY_ID": "fake",
"AWS_SECRET_ACCESS_KEY": "fake",
"AWS_DEFAULT_REGION": "us-east-1",
},
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
// 使用模拟器验证
awsSession := aws.NewAuthenticatedSession(t, "us-east-1")
bucketExists := aws.AssertS3BucketExists(t, awsSession, "test-bucket-001")
assert.True(t, bucketExists, "Bucket should exist after apply")
}
4.4.2 使用 Makefile 统一管理
创建 Makefile 来简化测试执行:
# Makefile
.PHONY: test test-aws test-gcp test-azure
test: test-aws test-gcp test-azure
test-aws:
cd test && go test -v -run TestAWS -timeout 30m
test-gcp:
STORAGE_EMULATOR_HOST=http://localhost:4443 \
cd test && go test -v -run TestGCP -timeout 30m
test-azure:
AZURITE_ACCOUNT_NAME=devstoreaccount1 \
AZURITE_ACCOUNT_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" \
cd test && go test -v -run TestAzure -timeout 30m
STORAGE_EMULATOR_HOST、AWS_ENDPOINT_URL)必须在测试执行前设置。建议在 Makefile 或 CI 配置中统一注入,避免硬编码在测试代码中。
4.5 验证环境连通性
完成配置后,运行以下命令验证环境是否正常工作:
# 启动所有模拟器
docker-compose up -d
# 运行测试
cd test && go test -v -run TestS3BucketCreation -timeout 10m
预期输出应包含:
=== RUN TestS3BucketCreation
basic_test.go:30: Running terraform init
basic_test.go:32: Running terraform apply
basic_test.go:38: Verifying S3 bucket exists
--- PASS: TestS3BucketCreation (12.45s)
如果测试失败,请检查:
- 模拟器容器是否正常运行(
docker ps) - 端口映射是否与测试代码中的 endpoint 一致
- Go 依赖是否完整下载(
go mod tidy)
至此,你的测试环境已搭建完成,可以开始编写针对 Terraform 模块的自动化测试用例了。