环境配置管理
pytest-dsl提供了强大的配置管理功能,支持多环境配置、动态配置切换、配置继承等特性,帮助您在不同环境间轻松切换测试配置。
配置文件概述
pytest-dsl支持YAML格式的配置文件,用于定义:
- HTTP客户端配置
- 数据库连接信息
- 环境特定的变量
- 测试执行参数
- 自定义设置
基本配置结构
基础配置文件示例
yaml
# config.yaml - 基础配置文件
http_clients:
default:
base_url: "https://api.example.com"
timeout: 30
headers:
Content-Type: "application/json"
User-Agent: "pytest-dsl/1.0"
admin:
base_url: "https://admin-api.example.com"
timeout: 60
headers:
Content-Type: "application/json"
Authorization: "Bearer ${ADMIN_TOKEN}"
variables:
api_version: "v1"
max_retry_count: 3
default_timeout: 30
test_settings:
parallel_workers: 4
report_format: "html"
log_level: "INFO"使用配置文件
bash
# 在命令行中指定配置文件
pytest-dsl tests/ --config config.yaml
# 指定多个配置文件,后面的会覆盖前面的
pytest-dsl tests/ --config base.yaml --config env-specific.yaml
# 使用YAML变量文件
pytest-dsl tests/ --yaml-vars config.yaml多环境配置
环境特定配置
为不同环境创建独立的配置文件:
yaml
# config/dev.yaml - 开发环境配置
environment: development
http_clients:
default:
base_url: "https://dev-api.example.com"
timeout: 15
headers:
Content-Type: "application/json"
X-Environment: "dev"
verify_ssl: false # 开发环境可能使用自签名证书
database:
host: "dev-db.example.com"
port: 5432
name: "dev_database"
user: "${DB_USER}"
password: "${DB_PASSWORD}"
variables:
debug_mode: true
log_level: "DEBUG"
test_data_prefix: "dev_test_"
cleanup_after_test: false
features:
enable_cache: false
enable_rate_limiting: false
mock_external_services: trueyaml
# config/test.yaml - 测试环境配置
environment: test
http_clients:
default:
base_url: "https://test-api.example.com"
timeout: 30
headers:
Content-Type: "application/json"
X-Environment: "test"
database:
host: "test-db.example.com"
port: 5432
name: "test_database"
user: "${DB_USER}"
password: "${DB_PASSWORD}"
variables:
debug_mode: false
log_level: "INFO"
test_data_prefix: "test_"
cleanup_after_test: true
features:
enable_cache: true
enable_rate_limiting: true
mock_external_services: falseyaml
# config/prod.yaml - 生产环境配置
environment: production
http_clients:
default:
base_url: "https://api.example.com"
timeout: 60
headers:
Content-Type: "application/json"
X-Environment: "prod"
retries: 3
database:
host: "prod-db.example.com"
port: 5432
name: "prod_database"
user: "${DB_USER}"
password: "${DB_PASSWORD}"
ssl_mode: "require"
variables:
debug_mode: false
log_level: "WARNING"
test_data_prefix: "prod_test_"
cleanup_after_test: true
test_settings:
max_test_duration: 300 # 生产环境测试时间限制
allowed_failure_rate: 0.05 # 允许5%的失败率
features:
enable_cache: true
enable_rate_limiting: true
mock_external_services: false配置继承
使用配置继承减少重复配置:
yaml
# config/base.yaml - 基础配置
http_clients:
default:
timeout: 30
headers:
Content-Type: "application/json"
User-Agent: "pytest-dsl/1.0"
Accept: "application/json"
retries: 2
variables:
api_version: "v1"
max_retry_count: 3
test_settings:
report_format: "html"
parallel_workers: 2yaml
# config/dev.yaml - 继承基础配置
extends: base.yaml
http_clients:
default:
base_url: "https://dev-api.example.com"
timeout: 15 # 覆盖基础配置
headers:
X-Environment: "development" # 添加新的头部
verify_ssl: false
variables:
debug_mode: true # 添加新变量
log_level: "DEBUG"
test_settings:
parallel_workers: 1 # 开发环境减少并发HTTP客户端配置
详细的HTTP客户端配置
yaml
http_clients:
# 默认API客户端
default:
base_url: "https://api.example.com"
timeout: 30
headers:
Content-Type: "application/json"
Accept: "application/json"
User-Agent: "pytest-dsl-client/1.0"
auth:
type: "bearer"
token: "${API_TOKEN}"
retries: 3
retry_delay: 1
verify_ssl: true
# 管理员API客户端
admin:
base_url: "https://admin-api.example.com"
timeout: 60
headers:
Content-Type: "application/json"
X-Admin-Client: "true"
auth:
type: "basic"
username: "${ADMIN_USER}"
password: "${ADMIN_PASSWORD}"
# 文件上传客户端
upload:
base_url: "https://upload.example.com"
timeout: 300 # 上传可能需要更长时间
headers:
User-Agent: "pytest-dsl-upload/1.0"
max_file_size: "100MB"
# 外部服务客户端
external:
base_url: "https://external-service.com"
timeout: 45
headers:
X-API-Key: "${EXTERNAL_API_KEY}"
X-Client-ID: "${CLIENT_ID}"
rate_limit:
requests_per_minute: 60认证配置
yaml
http_clients:
# Bearer Token认证
api_with_token:
base_url: "https://api.example.com"
auth:
type: "bearer"
token: "${ACCESS_TOKEN}"
# Basic认证
api_with_basic:
base_url: "https://api.example.com"
auth:
type: "basic"
username: "${API_USER}"
password: "${API_PASSWORD}"
# OAuth2认证
api_with_oauth:
base_url: "https://api.example.com"
auth:
type: "oauth2"
client_id: "${OAUTH_CLIENT_ID}"
client_secret: "${OAUTH_CLIENT_SECRET}"
token_url: "https://auth.example.com/oauth/token"
scope: "read write"
# 自定义头部认证
api_with_custom:
base_url: "https://api.example.com"
headers:
X-API-Key: "${CUSTOM_API_KEY}"
X-Client-Secret: "${CLIENT_SECRET}"环境变量和密钥管理
环境变量配置
yaml
# 在配置文件中引用环境变量
http_clients:
default:
base_url: "${API_BASE_URL}"
auth:
type: "bearer"
token: "${API_TOKEN}"
database:
host: "${DB_HOST}"
port: "${DB_PORT}"
user: "${DB_USER}"
password: "${DB_PASSWORD}"
variables:
environment_name: "${ENVIRONMENT}"
debug_enabled: "${DEBUG:-false}" # 带默认值密钥文件管理
bash
# .env.dev - 开发环境变量
API_BASE_URL=https://dev-api.example.com
API_TOKEN=dev_token_123456
DB_HOST=dev-db.example.com
DB_USER=dev_user
DB_PASSWORD=dev_password
ENVIRONMENT=development
DEBUG=true
# .env.test - 测试环境变量
API_BASE_URL=https://test-api.example.com
API_TOKEN=test_token_789012
DB_HOST=test-db.example.com
DB_USER=test_user
DB_PASSWORD=test_password
ENVIRONMENT=test
DEBUG=false
# .env.prod - 生产环境变量
API_BASE_URL=https://api.example.com
API_TOKEN=prod_token_345678
DB_HOST=prod-db.example.com
DB_USER=prod_user
DB_PASSWORD=prod_secure_password
ENVIRONMENT=production
DEBUG=false使用环境变量文件
bash
# 加载特定环境的变量文件
source .env.dev && pytest-dsl tests/ --config config/dev.yaml
# 或者使用工具自动加载
export ENVIRONMENT=dev
pytest-dsl tests/ --config config/${ENVIRONMENT}.yaml --env-file .env.${ENVIRONMENT}配置文件在DSL中的使用
访问配置变量
python
@name: "使用配置变量的测试"
# 在DSL中访问配置的变量
当前环境 = ${environment}
API版本 = ${api_version}
调试模式 = ${debug_mode}
[打印], 内容: "当前环境: ${当前环境}"
[打印], 内容: "API版本: ${API版本}"
# 根据配置调整测试行为
if ${调试模式} do
[打印], 内容: "调试模式已启用,将输出详细信息"
end
# 使用配置中的HTTP客户端
[HTTP请求], 客户端: "default", 配置: '''
method: GET
url: /api/${API版本}/status
asserts:
- ["status", "eq", 200]
'''条件配置
python
@name: "环境相关测试"
# 根据环境执行不同的测试逻辑
if "${environment}" == "development" do
# 开发环境特定的测试
[打印], 内容: "执行开发环境测试"
# 可能包含更详细的日志
调试输出 = True
elif "${environment}" == "production" do
# 生产环境的测试更加谨慎
[打印], 内容: "执行生产环境测试"
# 生产环境可能需要额外的确认
[断言], 条件: "${test_data_prefix} == 'prod_test_'", 消息: "生产环境测试数据前缀不正确"
else
# 测试环境的标准测试
[打印], 内容: "执行标准测试"
end
# 使用配置中的功能开关
if ${enable_cache} do
[测试缓存功能]
else
[跳过缓存测试]
end高级配置功能
配置模板和替换
yaml
# config/template.yaml - 配置模板
http_clients:
default:
base_url: "https://{{ENVIRONMENT}}-api.example.com"
timeout: "{{TIMEOUT}}"
headers:
X-Environment: "{{ENVIRONMENT}}"
X-Version: "{{API_VERSION}}"
variables:
data_prefix: "{{ENVIRONMENT}}_test_"
log_level: "{{LOG_LEVEL}}"bash
# 使用模板替换生成实际配置
export ENVIRONMENT=staging
export TIMEOUT=45
export API_VERSION=v2
export LOG_LEVEL=INFO
# 替换模板变量生成最终配置
envsubst < config/template.yaml > config/staging.yaml动态配置加载
python
# resources/common/config_manager.resource
@name: "配置管理器"
function 加载环境配置 (环境名称) do
[打印], 内容: "加载环境配置: ${环境名称}"
# 根据环境名称确定配置文件
配置文件路径 = "config/${环境名称}.yaml"
# 验证配置文件是否存在
[执行命令], 命令: "test -f ${配置文件路径}"
# 设置配置相关的全局变量
[设置全局变量], 变量名: "current_config", 值: ${配置文件路径}
[设置全局变量], 变量名: "current_environment", 值: ${环境名称}
[打印], 内容: "配置加载完成: ${配置文件路径}"
return {"config_file": ${配置文件路径}, "environment": ${环境名称}}
end
function 获取配置值 (配置路径, 默认值="") do
# 从当前配置中获取指定路径的值
# 这里需要实现配置值的读取逻辑
[打印], 内容: "获取配置值: ${配置路径}"
# 示例:假设配置已加载到全局变量中
config_result = [获取全局变量], 变量名: ${配置路径}
配置值 = ${config_result["result"]}
if "${配置值}" == "" and "${默认值}" != "" do
return ${默认值}
end
return ${配置值}
end
function 切换环境 (目标环境) do
[打印], 内容: "切换环境: ${目标环境}"
# 保存当前环境
env_result = [获取全局变量], 变量名: "current_environment"
当前环境 = ${env_result["result"]}
[设置全局变量], 变量名: "previous_environment", 值: ${当前环境}
# 加载新环境配置
新配置 = [加载环境配置], 环境名称: ${目标环境}
[打印], 内容: "环境切换完成: ${当前环境} -> ${目标环境}"
return ${新配置}
end配置验证
python
# resources/common/config_validator.resource
@name: "配置验证器"
function 验证HTTP客户端配置 (客户端名称) do
[打印], 内容: "验证HTTP客户端配置: ${客户端名称}"
# 检查基本配置项
必需配置项 = ["base_url", "timeout"]
for 配置项 in ${必需配置项} do
配置值 = [获取配置值], 配置路径: "http_clients.${客户端名称}.${配置项}"
[断言], 条件: "\"${配置值}\" != \"\"", 消息: "客户端${客户端名称}缺少必需配置: ${配置项}"
end
# 验证URL格式
基础URL = [获取配置值], 配置路径: "http_clients.${客户端名称}.base_url"
[断言], 条件: "'http' in '${基础URL}'", 消息: "基础URL格式无效: ${基础URL}"
# 验证超时值
超时值 = [获取配置值], 配置路径: "http_clients.${客户端名称}.timeout"
[断言], 条件: "${超时值} > 0", 消息: "超时值必须大于0: ${超时值}"
[打印], 内容: "✓ 客户端${客户端名称}配置验证通过"
return True
end
function 验证环境配置 () do
[打印], 内容: "验证当前环境配置"
# 验证环境变量
当前环境 = [获取配置值], 配置路径: "environment"
支持的环境 = ["development", "test", "staging", "production"]
[断言], 条件: "'${当前环境}' in ${支持的环境}", 消息: "不支持的环境: ${当前环境}"
# 验证所有HTTP客户端配置
客户端列表 = ["default", "admin"] # 根据实际配置调整
for 客户端 in ${客户端列表} do
[验证HTTP客户端配置], 客户端名称: ${客户端}
end
[打印], 内容: "✓ 环境配置验证完成"
return True
end配置文件示例集合
微服务架构配置
yaml
# config/microservices.yaml
http_clients:
# 用户服务
user_service:
base_url: "https://user-service.example.com"
timeout: 30
headers:
Content-Type: "application/json"
X-Service-Name: "user-service"
# 订单服务
order_service:
base_url: "https://order-service.example.com"
timeout: 45
headers:
Content-Type: "application/json"
X-Service-Name: "order-service"
# 支付服务
payment_service:
base_url: "https://payment-service.example.com"
timeout: 60
headers:
Content-Type: "application/json"
X-Service-Name: "payment-service"
auth:
type: "bearer"
token: "${PAYMENT_SERVICE_TOKEN}"
# 通知服务
notification_service:
base_url: "https://notification-service.example.com"
timeout: 20
headers:
Content-Type: "application/json"
X-Service-Name: "notification-service"
service_discovery:
consul:
host: "consul.example.com"
port: 8500
eureka:
url: "http://eureka.example.com:8761"
variables:
service_mesh_enabled: true
tracing_enabled: true
circuit_breaker_enabled: true数据库配置
yaml
# config/database.yaml
databases:
# 主数据库
primary:
host: "${PRIMARY_DB_HOST}"
port: 5432
name: "${PRIMARY_DB_NAME}"
user: "${PRIMARY_DB_USER}"
password: "${PRIMARY_DB_PASSWORD}"
ssl_mode: "require"
pool_size: 10
# 只读副本
readonly:
host: "${READONLY_DB_HOST}"
port: 5432
name: "${PRIMARY_DB_NAME}"
user: "${READONLY_DB_USER}"
password: "${READONLY_DB_PASSWORD}"
ssl_mode: "require"
pool_size: 5
# Redis缓存
cache:
host: "${REDIS_HOST}"
port: 6379
password: "${REDIS_PASSWORD}"
db: 0
# MongoDB文档数据库
document:
host: "${MONGO_HOST}"
port: 27017
name: "${MONGO_DB_NAME}"
user: "${MONGO_USER}"
password: "${MONGO_PASSWORD}"
connection_pools:
max_connections: 20
min_connections: 5
idle_timeout: 300配置最佳实践
1. 安全性考虑
yaml
# 不要在配置文件中硬编码敏感信息
# ❌ 错误做法
http_clients:
default:
auth:
token: "hardcoded_secret_token" # 不安全
# ✅ 正确做法
http_clients:
default:
auth:
token: "${API_TOKEN}" # 使用环境变量2. 配置分层
config/
├── base.yaml # 基础配置
├── environments/ # 环境特定配置
│ ├── dev.yaml
│ ├── test.yaml
│ └── prod.yaml
├── services/ # 服务特定配置
│ ├── api_clients.yaml
│ └── databases.yaml
└── features/ # 功能开关配置
├── feature_flags.yaml
└── experiments.yaml3. 配置验证脚本
bash
#!/bin/bash
# scripts/validate_config.sh
echo "验证配置文件..."
for env in dev test staging prod; do
echo "验证环境: $env"
# 检查配置文件是否存在
if [ ! -f "config/$env.yaml" ]; then
echo "错误: 配置文件 config/$env.yaml 不存在"
exit 1
fi
# 验证YAML语法
python -c "import yaml; yaml.safe_load(open('config/$env.yaml'))" || {
echo "错误: config/$env.yaml YAML语法错误"
exit 1
}
echo "✓ $env 配置验证通过"
done
echo "所有配置文件验证完成"4. 配置文档化
yaml
# config/schema.yaml - 配置架构文档
# 用于说明配置文件的结构和用途
http_clients:
description: "HTTP客户端配置"
required: true
properties:
default:
description: "默认API客户端"
required: true
properties:
base_url:
type: "string"
description: "API基础URL"
required: true
timeout:
type: "integer"
description: "请求超时时间(秒)"
default: 30
headers:
type: "object"
description: "默认请求头"
variables:
description: "全局变量配置"
properties:
debug_mode:
type: "boolean"
description: "是否启用调试模式"
default: false通过合理的配置管理,您可以在不同环境间灵活切换,保持配置的一致性和安全性,提高测试的可维护性和可靠性。