
摘要 上一篇我们教会了 AI “看懂”流程图,并输出结构化的节点与边。但这只是开始——真正的挑战在于:如何系统性、无遗漏地遍历所有可能的执行路径? 人工拆分极易出错,尤其面对循环、多出口等复杂逻辑。本文将手把手教你利用 **Python 图论库
networkx**,构建一个“需求-测试”自动转换引擎,实现从流程图 JSON 到 Pytest 用例的端到端生成,并详解循环处理、路径去重、断言注入等工程细节。
在上一篇《让 AI “看见”需求》中,我们成功将一张用户注册流程图转化为如下结构化数据:
json编辑
{
"nodes": [{"id": "n1", "label": "输入手机号"}, ...],
"edges": [
{"from": "n1", "to": "n2", "condition": "手机号有效?"},
{"from": "n1", "to": "n1", "condition": "手机号无效?"} // ← 这是一个循环!
]
}
然而,这份数据本身还不是测试用例。测试的核心是覆盖所有可能的业务路径。对于上述流程,至少存在两条关键路径:
n1 (有效) → n2 → n3 → 成功n1 (无效) → n1 (重试) → ... → 最终放弃或修正如果仅靠人工从 JSON 中梳理路径,面对包含 10+ 节点、多个判断和循环的复杂流程(如 ADAS 功能状态机),几乎必然遗漏分支。
我们需要一个“路径引擎”,能像数学家一样严谨地穷尽所有可能性。
在计算机科学中,流程图本质上是一个 有向图 (Directed Graph):
而我们的目标,就是找出图中从入口到出口的所有简单路径(Simple Paths)。
networkx**?matplotlib + pygraphviz)。python编辑
import networkx as nx
def build_graph_from_json(data):
G = nx.DiGraph() # 创建有向图
# 添加节点
for node in data["nodes"]:
G.add_node(node["id"], label=node["label"])
# 添加带条件的边
for edge in data["edges"]:
G.add_edge(
edge["from"],
edge["to"],
condition=edge["condition"]
)
return G
并非所有节点都是起点或终点。我们需要定义规则:
python编辑
def find_entry_exit_nodes(G):
entry_nodes = [n for n, d in G.in_degree() if d == 0]
exit_nodes = [n for n, d in G.out_degree() if d == 0]
# 补充:显式标记的出口(如标签含"成功")
for node, attr in G.nodes(data=True):
if "成功" in attr["label"] or "失败" in attr["label"]:
if node not in exit_nodes:
exit_nodes.append(node)
return entry_nodes, exit_nodes
这是最复杂的一步。networkx 的 all_simple_paths 函数天然不支持循环(会陷入无限递归)。
我们的策略:设置最大循环次数(如 3 次)
python编辑
def find_all_paths_with_loop(G, entry, exits, max_loops=3):
all_paths = []
def dfs(current, path, visited_count):
# 终止条件1: 到达出口
if current in exits:
all_paths.append(path.copy())
return
# 终止条件2: 循环超限
if visited_count.get(current, 0) > max_loops:
return
# 更新访问计数
visited_count[current] = visited_count.get(current, 0) + 1
# 递归探索邻居
for neighbor in G.successors(current):
path.append(neighbor)
dfs(neighbor, path, visited_count.copy()) # 传递副本避免污染
path.pop() # 回溯
dfs(entry, [entry], {})
return all_paths
💡 **为什么用
visited_count.copy()**? 因为 Python 字典是引用传递。若不复制,在回溯时计数器状态会被错误修改,导致路径漏算。
有时不同路径会收敛到相同状态序列(如重试 2 次 vs 3 次后都成功)。我们可以根据业务重要性做裁剪:
python编辑
# 按路径长度排序,取前 N 条
all_paths.sort(key=len)
selected_paths = all_paths[:10] # 根据实际需求调整
有了路径列表,下一步是将其“翻译”成可执行的测试代码。
我们需要一个节点行为字典,将流程图中的抽象节点映射为具体的测试操作:
python编辑
NODE_ACTIONS = {
"输入手机号": lambda page: page.input_phone("13800138000"),
"发送验证码": lambda page: page.click_send_code(),
"验证成功": lambda page: assert page.is_on_success_page()
}
python编辑
def generate_test_case(path_id, path, G):
code_lines = [f"def test_path_{path_id}():", ' """']
# 生成路径描述
labels = [G.nodes[n]["label"] for n in path]
code_lines.append(f" 自动路径: {' -> '.join(labels)}")
code_lines.append(' """')
# 生成操作与断言
for node_id in path:
label = G.nodes[node_id]["label"]
if label in NODE_ACTIONS:
action = NODE_ACTIONS[label].__code__.co_consts[0] # 简化示例
code_lines.append(f" {action}")
else:
# 默认操作:记录日志
code_lines.append(f" # 执行: {label}")
return "\n".join(code_lines)
对于决策节点(如“验证码正确?”),我们应在路径中显式注入断言:
python编辑
# 在路径遍历时,检查边的 condition
for i in range(len(path)-1):
edge_data = G[path[i]][path[i+1]]
condition = edge_data["condition"]
if "正确" in condition:
code_lines.append(" assert page.get_code_status() == 'valid'")
elif "无效" in condition:
code_lines.append(" assert page.has_error('验证码错误')")
让我们用一个真实的 ACC(自适应巡航)状态机 来验证方案。
OFF → STANDBY → ACTIVE → OVERRIDE → FAULTACTIVE 可因跟车距离过近进入 OVERRIDE,松开油门后又回到 ACTIVEFAULT 是异常终止态json编辑
{
"nodes": [
{"id": "s1", "label": "ACC OFF"},
{"id": "s2", "label": "ACC STANDBY"},
{"id": "s3", "label": "ACC ACTIVE"}
],
"edges": [
{"from": "s1", "to": "s2", "condition": "按下 ACC 按钮"},
{"from": "s2", "to": "s3", "condition": "车速 > 30km/h"},
{"from": "s3", "to": "s2", "condition": "车速 < 30km/h"} // ← 循环
]
}
s1 → s2 → s3 (正常激活)s1 → s2 → s3 → s2 (降速退出)s1 → s2 → s3 → s2 → s3 (二次激活)📊 效果:原本需要 1 天人工设计的状态机测试,现在 10 分钟内自动生成 15+ 条高价值路径,且 100% 覆盖状态转移规则。
复杂流程可能产生数千条路径。
应对:
生成的用例依赖 Page Object 或 API Client。
应对:
在生成脚本头部自动注入 fixture 声明: python编辑
# 自动生成
import pytest
from pages.acc_page import ACCPage
@pytest.fixture
def acc_page():
return ACCPage()
当流程图变更,如何同步更新用例?
应对:
图论,这门诞生于 18 世纪的古老数学分支,今天正成为智能测试的新基石。通过将业务流程抽象为有向图,并用算法穷尽其所有路径,我们得以系统性地消除测试盲区,尤其是在 ADAS、智能座舱等高复杂度领域。
这不仅是提效,更是质量保障范式的升级——从依赖个人经验的“艺术”,走向可重复、可验证的“工程”。