当多个API属于同一业务功能场景(如白名单管理的增删改查),需要按场景整体规划测试,而非逐个API独立编写。本文档总结编写场景型接口自动化的经验和注意事项。
---
场景型接口是指一组在业务上紧密关联、形成完整CRUD闭环的API集合。典型特征:
| 特征 | 示例 |
|------|------|
| 同一资源的增删改查 | AddWhiteListGroup / DeleteWhiteListGroup / ModifyWhiteListGroup / DescribeWhiteListGroup |
| 操作之间有前置依赖 | 必须先Add才能Modify/Delete |
| 共享同一组参数规则 | 分组名命名规则、IP格式要求对多个API通用 |
| 需要跨API验证 | Add之后用Describe验证,Delete之后用Describe确认删除 |
**已完成的场景型接口案例**:
- 白名单管理:ModifyIpWhiteList + AddWhiteListGroup + DeleteWhiteListGroup + ModifyWhiteListGroup + DescribeWhiteListGroup(5个API,41个测试用例)
---
单API编写时只需关注自身参数,场景型要先理清API间的依赖关系和执行顺序:
```
1. 梳理API关系图
DescribeWhiteListGroup (查询) ← 所有写操作的验证手段
AddWhiteListGroup (创建) → ModifyWhiteListGroup (修改) → DeleteWhiteListGroup (删除)
ModifyIpWhiteList (修改全局) ← 独立,但共享IP格式规则
2. 确定编写顺序
先写查询(Describe) → 再写创建(Add) → 再写修改(Modify) → 最后写删除(Delete)
原因:查询API是其他API的验证手段,必须先确保它能工作
3. 识别共享约束
- 分组名规则:1-64字符,只允许中文/英文/数字
- IP格式:CIDR表示法,逗号分隔
- 这些约束在多个API的异常值测试中共享
```
场景型接口一次性涉及多个service方法,必须批量检查SDK参数与service封装是否一致:
```python
```
```python
def test_add_white_list_group_basic(self, setup_clients, instance_data):
"""P0用例必须是完整闭环,不能只调一下API就算通过"""
service.wait_for_instance_status(cacheInstanceId)
success, result = service.add_white_list_group(cacheInstanceId, group_name, ips=test_ips)
assert success, f"添加失败: {result}"
query_success, query_result = service.describe_white_list_group(cacheInstanceId)
assert query_success
group_names = [g.get('name') for g in query_result['whiteLists']]
assert group_name in group_names, f"新分组未在列表中"
service.delete_white_list_group(cacheInstanceId, group_name)
```
```python
def test_delete_white_list_group_basic(self, setup_clients, instance_data):
"""Delete测试不能依赖已存在的数据,必须自己创建"""
service.add_white_list_group(cacheInstanceId, test_group_name, ips="10.0.0.1/32")
success, result = service.delete_white_list_group(cacheInstanceId, test_group_name)
assert success
query_result = service.describe_white_list_group(cacheInstanceId)
group_names = [g.get('name') for g in query_result['whiteLists']]
assert test_group_name not in group_names, "删除后分组仍存在"
```
```python
def test_modify_white_list_group_basic(self, setup_clients, instance_data):
"""Modify测试需要自建数据,修改后验证,最后清理"""
service.add_white_list_group(cacheInstanceId, test_group_name, ips=original_ips)
success, result = service.modify_white_list_group(cacheInstanceId, test_group_name, new_ips)
assert success
query_result = service.describe_white_list_group(cacheInstanceId)
target = [g for g in query_result['whiteLists'] if g['name'] == test_group_name]
assert new_ips in target[0]['ips']
service.delete_white_list_group(cacheInstanceId, test_group_name)
```
```python
def test_modify_ip_white_list_basic(self, setup_clients, instance_data):
"""修改全局配置(如IP白名单)必须先保存原始值,测试完恢复"""
_, original_result = service.describe_ip_white_list(cacheInstanceId)
original_ips = original_result.get('ipWhiteList', [])
success, result = service.modify_ip_white_list(cacheInstanceId, test_ips)
assert success
_, verify_result = service.describe_ip_white_list(cacheInstanceId)
if original_ips:
service.modify_ip_white_list(cacheInstanceId, original_ips)
```
---
**踩坑经验**:白名单分组名只允许中文、英文字母和数字,使用 `autotest_add_12345`(含下划线)被API拒绝。
```python
test_group_name = f"autotest_add_{int(time.time()) % 100000}"
test_group_name = f"autotestadd{int(time.time()) % 100000}"
```
**通用规则**:生成测试数据名称前,先确认目标API的参数校验规则。
```python
import time
test_group_name = f"autotestmod{int(time.time()) % 100000}"
```
```python
service.wait_for_instance_status(cacheInstanceId)
service.modify_white_list_group(...)
service.wait_for_instance_status(cacheInstanceId)
service.delete_white_list_group(...)
```
```python
del_success, del_result = service.delete_white_list_group(cacheInstanceId, test_group_name)
if not del_success:
logging.warning(f"清理分组失败: {del_result}")
```
除了单API的错误处理外,场景型测试的P1应覆盖:
| 测试场景 | 覆盖API | 预期 |
|---------|---------|------|
| 重复创建同名分组 | Add + Add | 第二次返回409冲突 |
| 删除不存在的分组 | Delete | 返回错误 |
| 修改不存在的分组 | Modify | 返回错误 |
| 删除系统默认分组 | Delete(default) | 返回错误,不允许删除 |
| 修改系统默认分组IP | Modify(default) | 允许修改(但需恢复) |
同一场景下的多个API通常共享相同的参数规则,异常值测试的参数化数据可以复用:
```python
INVALID_GROUP_NAMES = [
("", "空字符串"),
("a" * 256, "超长名称"),
("特殊字符@#$%", "特殊字符"),
]
INVALID_IPS = [
("invalid-ip", "格式错误"),
("999.999.999.999/32", "无效IP段"),
("192.168.1.1/33", "无效CIDR掩码"),
]
```
场景型接口一次涉及多个service方法,修复前必须逐一对照SDK:
```
对每个API执行以下检查:
□ 读SDK的 {ApiName}Parameters 类源码
□ 确认构造函数的必填参数列表和顺序
□ 确认有哪些 setXxx() 方法(可选参数)
□ 确认service方法的参数是否与SDK对齐
□ 确认参数类型(字符串/列表/字典)
```
---
| API类型 | P0 | P1 | P2 | 合计 |
|---------|----|----|-----|------|
| Describe(查询) | 1 | 3(错误处理、字段结构、默认值) | 2(边界、异常ID) | 6 |
| Add(创建) | 1(创建+验证+清理) | 3(错误处理、不带可选参数、重复创建) | 1(异常名称) | 5+ |
| Delete(删除) | 1(创建+删除+验证) | 3(错误处理、不存在、删default) | 1(异常名称) | 5+ |
| Modify(修改) | 1(创建+修改+验证+清理) | 3(错误处理、不存在、修改default) | 1(异常IP) | 5+ |
| ModifyGlobal(全局修改) | 1(保存+修改+验证+恢复) | 3(错误处理、多值、特殊值) | 1(异常格式) | 5+ |
白名单场景总计:5个API → 41个测试用例(含参数化展开)
---
- [踩坑经验 - lessons_learned.md](lessons_learned.md)
- [排查指南 - error_debugging_guide.md](error_debugging_guide.md)
- [完整示例 - complete_example.md](complete_example.md)
- [Skill 主文档 - ../SKILL.md](../SKILL.md)