流程控制
流程控制是编程的核心概念,pytest-dsl提供了直观的条件判断和循环语法,让您能够创建复杂的测试逻辑。
条件判断
if语句
基本的条件判断语法:
python
# 基本if语句
status = "success"
if status == "success" do
[打印], 内容: "测试通过"
end
# 使用变量的条件判断
user_age = 25
if ${user_age} >= 18 do
[打印], 内容: "用户已成年"
endif-else语句
python
# if-else语句
environment = "production"
if environment == "development" do
[打印], 内容: "开发环境:启用调试模式"
debug_mode = True
else
[打印], 内容: "生产环境:关闭调试模式"
debug_mode = False
end
# 数值比较
score = 85
if ${score} >= 90 do
grade = "A"
else
grade = "B"
end
[打印], 内容: "分数: ${score}, 等级: ${grade}"if-elif-else语句
python
# 多重条件判断
http_status = 200
if ${http_status} == 200 do
[打印], 内容: "请求成功"
result = "success"
elif ${http_status} == 404 do
[打印], 内容: "资源未找到"
result = "not_found"
elif ${http_status} >= 500 do
[打印], 内容: "服务器错误"
result = "server_error"
else
[打印], 内容: "其他状态码: ${http_status}"
result = "unknown"
end
[打印], 内容: "处理结果: ${result}"复杂条件表达式
python
# 逻辑运算符
user_role = "admin"
user_active = True
if user_role == "admin" and ${user_active} do
[打印], 内容: "管理员用户且状态活跃"
access_level = "full"
end
# 多条件组合
age = 25
country = "China"
if ${age} >= 18 and country == "China" do
[打印], 内容: "符合条件的中国成年用户"
end
# 使用or运算符
user_type = "premium"
if user_type == "premium" or user_type == "vip" do
[打印], 内容: "高级用户,享受特殊权限"
end
# 使用not运算符
is_banned = False
if not ${is_banned} do
[打印], 内容: "用户未被封禁,可以正常使用"
end嵌套条件
python
# 嵌套if语句
user_type = "admin"
user_department = "IT"
if user_type == "admin" do
[打印], 内容: "用户是管理员"
if user_department == "IT" do
[打印], 内容: "IT部门管理员,拥有系统权限"
system_access = True
else
[打印], 内容: "其他部门管理员,拥有业务权限"
system_access = False
end
[打印], 内容: "系统访问权限: ${system_access}"
end循环结构
for循环
数值范围循环
python
# 基本for循环
for i in range(1, 6) do
[打印], 内容: "第 ${i} 次循环"
end
# 使用变量定义范围
max_count = 5
for j in range(1, ${max_count} + 1) do
[打印], 内容: "计数: ${j}"
end
# 从0开始的循环
for k in range(0, 5) do
[打印], 内容: "索引: ${k}"
end列表循环
python
# 直接遍历列表
users = ["张三", "李四", "王五"]
for user in users do
[打印], 内容: "处理用户: ${user}"
end
# 遍历数字列表
numbers = [1, 2, 3, 4, 5]
total = 0
for number in numbers do
total = total + number
[打印], 内容: "当前数字: ${number}, 累计: ${total}"
end
# 需要索引时,仍可使用range配合预定义长度
users_length = 3
for i in range(0, ${users_length}) do
[打印], 内容: "第 ${i} 个用户: ${users[i]}"
end字典循环
python
# 遍历字典键值对
user_info = {"name": "张三", "age": 30, "city": "北京"}
for key, value in user_info do
[打印], 内容: "${key}: ${value}"
end
# 单变量遍历字典时,循环变量是字典的键
for key in user_info do
[打印], 内容: "字段: ${key}, 值: ${user_info[key]}"
end对象列表循环
python
users = [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30}
]
for user in users do
[打印], 内容: "用户: ${user.name}, 年龄: ${user.age}"
end循环控制语句
break语句
python
# 使用break退出循环
for i in range(1, 11) do
if ${i} == 5 do
[打印], 内容: "达到5,退出循环"
break
end
[打印], 内容: "当前数字: ${i}"
end
# 在条件满足时退出
users = ["admin", "user1", "user2", "guest"]
for user in users do
[打印], 内容: "检查用户: ${user}"
if ${user} == "guest" do
[打印], 内容: "找到访客用户,停止搜索"
break
end
endcontinue语句
python
# 使用continue跳过当前迭代
for i in range(1, 11) do
# 跳过偶数
if ${i} % 2 == 0 do
continue
end
[打印], 内容: "奇数: ${i}"
end
# 跳过特定条件
test_cases = ["case1", "skip_case", "case2", "case3"]
for test_case in test_cases do
if ${test_case} == "skip_case" do
[打印], 内容: "跳过测试用例: ${test_case}"
continue
end
[打印], 内容: "执行测试用例: ${test_case}"
end嵌套循环
python
# 嵌套循环示例
environments = ["dev", "test", "prod"]
test_types = ["unit", "integration", "e2e"]
for environment in environments do
[打印], 内容: "环境: ${environment}"
for test_type in test_types do
[打印], 内容: " 执行 ${test_type} 测试"
# 模拟测试执行
if ${environment} == "prod" and ${test_type} == "unit" do
[打印], 内容: " 生产环境跳过单元测试"
continue
end
[打印], 内容: " ${environment} 环境的 ${test_type} 测试完成"
end
end实际应用场景
1. API测试中的条件处理
python
# 根据环境选择不同的API地址
environment = "development"
if environment == "development" do
api_base = "https://dev-api.example.com"
timeout = 60
elif environment == "testing" do
api_base = "https://test-api.example.com"
timeout = 30
else
api_base = "https://api.example.com"
timeout = 10
end
[打印], 内容: "使用API地址: ${api_base}, 超时: ${timeout}秒"
# 执行API测试
[HTTP请求], 客户端: "default", 配置: '''
method: GET
url: ${api_base}/health
timeout: ${timeout}
asserts:
- ["status", "eq", 200]
''', 步骤名称: "健康检查"2. 批量用户测试
python
# 批量测试多个用户
test_users = [
{"username": "admin", "password": "admin123", "role": "admin"},
{"username": "user1", "password": "user123", "role": "user"},
{"username": "guest", "password": "guest123", "role": "guest"}
]
for test_user in test_users do
username = test_user["username"]
password = test_user["password"]
role = test_user["role"]
[打印], 内容: "测试用户: ${username} (${role})"
# 模拟登录
[HTTP请求], 客户端: "default", 配置: '''
method: POST
url: /api/login
request:
json:
username: "${username}"
password: "${password}"
captures:
login_status: ["jsonpath", "$.status"]
user_token: ["jsonpath", "$.token"]
asserts:
- ["status", "eq", 200]
''', 步骤名称: "用户${username}登录"
# 根据角色执行不同的测试
if role == "admin" do
[打印], 内容: "执行管理员权限测试"
# 管理员特有的测试
elif role == "user" do
[打印], 内容: "执行普通用户权限测试"
# 普通用户测试
else
[打印], 内容: "执行访客权限测试"
# 访客测试
end
end3. 错误重试机制
python
# 实现重试机制
max_retries = 3
retry_count = 0
success = False
for attempt in range(1, ${max_retries} + 1) do
[打印], 内容: "第 ${attempt} 次尝试"
# 模拟可能失败的操作
[HTTP请求], 客户端: "default", 配置: '''
method: GET
url: /api/unstable-endpoint
captures:
response_status: ["status"]
''', 步骤名称: "尝试访问不稳定接口"
if ${response_status} == 200 do
[打印], 内容: "请求成功!"
success = True
break
else
[打印], 内容: "请求失败,状态码: ${response_status}"
if ${attempt} < ${max_retries} do
[打印], 内容: "等待重试..."
[等待], 秒数: 2
end
end
end
if not ${success} do
[打印], 内容: "所有重试都失败了"
[断言], 条件: "False", 消息: "接口请求最终失败"
end4. 数据验证循环
python
# 验证API返回的数据列表
[HTTP请求], 客户端: "default", 配置: '''
method: GET
url: /api/users
captures:
users_data: ["json"]
asserts:
- ["status", "eq", 200]
''', 步骤名称: "获取用户列表"
# 验证每个用户数据的完整性
required_fields = ["id", "name", "email", "status"]
for user in users_data do
user_id = user["id"]
[打印], 内容: "验证用户 ${user_id} 的数据"
for field in required_fields do
if field in user do
[打印], 内容: " ✓ 字段 ${field} 存在"
else
[打印], 内容: " ✗ 字段 ${field} 缺失"
[断言], 条件: "False", 消息: "用户${user_id}缺少必需字段${field}"
end
end
# 验证邮箱格式
user_email = user["email"]
if "@" in user_email do
[打印], 内容: " ✓ 邮箱格式正确: ${user_email}"
else
[打印], 内容: " ✗ 邮箱格式错误: ${user_email}"
end
end5. 条件测试执行
python
# 根据配置决定是否执行某些测试
run_performance_tests = False
run_security_tests = True
test_environment = "staging"
[打印], 内容: "开始执行测试套件"
# 基础功能测试(总是执行)
[打印], 内容: "执行基础功能测试"
[HTTP请求], 客户端: "default", 配置: '''
method: GET
url: /api/health
asserts:
- ["status", "eq", 200]
''', 步骤名称: "健康检查"
# 性能测试(条件执行)
if ${run_performance_tests} do
[打印], 内容: "执行性能测试"
for i in range(1, 101) do
[HTTP请求], 客户端: "default", 配置: '''
method: GET
url: /api/fast-endpoint
asserts:
- ["status", "eq", 200]
- ["response_time", "lt", 100]
''', 步骤名称: "性能测试 ${i}"
end
else
[打印], 内容: "跳过性能测试"
end
# 安全测试(条件执行)
if ${run_security_tests} and test_environment != "production" do
[打印], 内容: "执行安全测试"
# SQL注入测试
malicious_inputs = ["'; DROP TABLE users; --", "1' OR '1'='1", "<script>alert('xss')</script>"]
for payload in malicious_inputs do
[打印], 内容: "测试恶意输入: ${payload}"
[HTTP请求], 客户端: "default", 配置: '''
method: POST
url: /api/search
request:
json:
query: "${payload}"
asserts:
- ["status", "in", [400, 403]]
''', 步骤名称: "安全测试 - 恶意输入"
end
else
[打印], 内容: "跳过安全测试"
end最佳实践
1. 避免过深的嵌套
python
# 不好的做法:过深嵌套
if condition1 do
if condition2 do
if condition3 do
if condition4 do
# 代码逻辑
end
end
end
end
# 好的做法:使用早期返回或组合条件
if condition1 and condition2 and condition3 and condition4 do
# 代码逻辑
end2. 使用有意义的变量名
python
# 不好的做法
for i in range(0, 10) do
for j in range(0, 5) do
# 不清楚i和j代表什么
end
end
# 好的做法
for test_case_index in range(0, 10) do
for retry_attempt in range(0, 5) do
# 变量名清晰表达意图
end
end3. 适当使用注释
python
# 复杂的条件判断应该添加注释
user_score = 85
user_level = "premium"
# 检查用户是否符合高级功能使用条件
if ${user_score} >= 80 and user_level == "premium" do
[打印], 内容: "用户符合高级功能使用条件"
enable_advanced_features = True
end4. 合理使用循环控制
python
# 在适当的时候使用break和continue
found_target = False
target_id = 123
for item in item_list do
item_id = item["id"]
# 跳过无效项目
if item["status"] != "active" do
continue
end
# 找到目标后立即退出
if ${item_id} == ${target_id} do
[打印], 内容: "找到目标项目: ${item_id}"
found_target = True
break
end
end
if not ${found_target} do
[打印], 内容: "未找到目标项目"
end常见问题
1. 条件表达式错误
python
# 错误:字符串比较时忘记引号
status = "success"
if status == success do # 错误:success应该是"success"
[打印], 内容: "成功"
end
# 正确写法
if status == "success" do
[打印], 内容: "成功"
end2. 循环变量作用域
python
# 注意:循环变量在循环外仍然可用
for i in range(0, 5) do
[打印], 内容: "循环中: ${i}"
end
# 循环结束后,i仍然是最后一次的值
[打印], 内容: "循环外: ${i}" # 输出: 循环外: 43. 无限循环风险
python
# 避免可能的无限循环
counter = 0
max_iterations = 100
for i in range(0, ${max_iterations}) do
# 确保有退出条件
if some_condition do
break
end
counter = counter + 1
if ${counter} >= ${max_iterations} do
[打印], 内容: "达到最大迭代次数,强制退出"
break
end
end下一步
现在您已经掌握了pytest-dsl的流程控制,可以继续学习:
- 内置关键字 - 了解框架提供的功能
- 自定义关键字 - 创建可复用的测试组件
- HTTP API测试 - 在API测试中应用流程控制
- 数据驱动测试 - 结合循环实现数据驱动测试