基于 Dify 知识库 + Ollama 大模型,自动生成测试用例并导出 XMind 的完整方案

基于 Dify 知识库 + Ollama 大模型,自动生成测试用例并导出 XMind 的完整方案

告别手动写测试用例,让 AI 帮你从知识库中提取业务信息,自动生成高质量测试用例

---最近很多测试应该使用AI skill方法生成测试用例,那有其他什么方式进一步提高测试用例的准确性,估计要用到了知识库,本文大概整理出一套落地思路

一、背景

在日常测试工作中,编写测试用例是一项耗时且重复的工作。尤其是当业务逻辑复杂、涉及多个模块时,测试人员需要:

  1. 翻阅大量需求文档、产品说明
  2. 理解业务逻辑,提取关键信息
  3. 应用各种测试设计方法(等价类、场景法、正交实验法等)
  4. 逐条编写测试用例,整理成 Excel 或 XMind

这个过程不仅耗时,而且容易遗漏边界场景和异常情况。

我们的目标:构建一个自动化工具,能够:

  • 从 Dify 知识库中检索与需求相关的业务文档
  • 利用本地部署的 LLM(Ollama + deepseek-r1:7b)理解业务逻辑
  • 内置多种测试设计方法(等价类、场景法、正交实验法、异常测试、接口测试)
  • 自动生成测试用例,并输出为 XMind 思维导图 + Excel 表格

二、思路

整个方案的设计思路可以用一句话概括:

知识检索 → 智能生成 → 结构化输出

具体来说:

1. 为什么用 Dify 知识库?

很多公司已经有沉淀的业务文档(PRD、接口文档、操作手册等),但这些文档散落在各处,难以被有效利用。Dify 提供了开箱即用的 RAG(检索增强生成)能力,支持上传文档、自动分块、向量化存储,并提供 Retrieval API。

2. 为什么用本地 Ollama?

考虑到数据安全和隐私,很多企业不允许将业务数据上传到公有云大模型。通过 Ollama 在本地部署开源模型(如 deepseek-r1:7b),既能保证数据不外泄,又能获得不错的生成质量。

3. 为什么设计 Skill 插件机制?

不同的业务场景需要不同的测试设计方法:

  • 表单验证 → 等价类划分 + 边界值分析
  • 业务流程 → 场景法(基本流、备选流、异常流)
  • 多参数组合 → 正交实验法(Pairwise)
  • 系统稳定性 → 异常/容错测试
  • API 接口 → 接口测试(参数校验 + 状态码覆盖)

通过 Skill 插件机制,每种方法独立实现,可以自由组合,也方便后续扩展。

4. 为什么输出 XMind?

XMind 是测试人员最常用的思维导图工具,适合展示用例的结构层次。同时导出 Excel 方便统计和归档。两者互补,满足不同场景的需求。


三、整体架构

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                         main.py (主流程编排)                          │
│                                                                     │
│   ┌─────────── 步骤 1 ───────────┐  ┌──────── 步骤 2 ──────────┐   │
│   │     Dify 知识库检索           │  │     LLM 生成测试用例       │   │
│   │                               │  │                          │   │
│   │  ┌─────────────────────┐     │  │  ┌──────────────────┐    │   │
│   │  │  DifyRetriever      │     │  │  │  LLMClient       │    │   │
│   │  │  ┌───────────────┐  │     │  │  │  ┌────────────┐  │    │   │
│   │  │  │ Dify 知识库    │  │─────┼──┼──│  │ Ollama API │  │    │   │
│   │  │  │ Retrieval API │  │     │  │  │  │ (streaming) │  │    │   │
│   │  │  └───────────────┘  │     │  │  │  └────────────┘  │    │   │
│   │  └─────────────────────┘     │  │  └────────┬─────────┘    │   │
│   └──────────────────────────────┘  └───────────┼──────────────┘   │
│                                                  │                 │
│                                                  ▼                 │
│                                   ┌──────────────────────────┐    │
│                                   │     skills/ 插件层        │    │
│                                   │  ┌────────────────────┐  │    │
│                                   │  │ equivalence.py    │  │    │
│                                   │  │ scenario.py       │  │    │
│                                   │  │ orthogonal.py     │  │    │
│                                   │  │ exception.py      │  │    │
│                                   │  │ api_test.py       │  │    │
│                                   │  └────────────────────┘  │    │
│                                   └──────────────────────────┘    │
│                                                                     │
│   ┌──────────────────── 步骤 3 ────────────────────────────────┐   │
│   │              xmind_generator.py                             │   │
│   │                                                             │   │
│   │  表格解析 → 列头自动映射 → 去重 → 质量过滤 → 统计 → 生成   │   │
│   │                                                             │   │
│   │  ┌──────────┐    ┌──────────┐    ┌──────────────────────┐  │   │
│   │  │ XMind    │    │ Excel    │    │ 统计报告 (控制台)    │  │   │
│   │  │ .xmind   │    │ .xlsx    │    │ P0/P1/P2 分布        │  │   │
│   │  └──────────┘    └──────────┘    └──────────────────────┘  │   │
│   └─────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘

各模块职责

模块 文件 职责
主入口 main.py 编排三步流程,解析命令行参数
知识库检索 dify_retriever.py 通过 Dify API 检索相关文档片段
LLM 生成 llm_client.py 调用 Ollama 流式生成测试用例
Skill 插件 skills/*.py 各种测试设计方法的 Prompt 模板
输出生成 xmind_generator.py 解析 LLM 输出 → 去重/过滤 → XMind + Excel
配置 config.py 全局配置项

四、核心流程详解

整体流程图

复制代码
开始
  │
  ▼
┌──────────────────────────────┐
│  输入:需求描述文本           │
│  例:"用户登录功能"           │
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│  步骤 1:检索知识库           │
│                              │
│  DifyRetriever.retrieve()    │
│    → 语义搜索                │
│    → 返回 Top-K 相关文档     │
│    → 格式化为上下文           │
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│  步骤 2:LLM 生成测试用例     │
│                              │
│  LLMClient.generate()        │
│    → 拼接 Prompt             │
│      = 需求 + 知识库 + Skill │
│    → 流式调用 Ollama         │
│    → 实时显示生成进度         │
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│  步骤 3:解析并输出           │
│                              │
│  ① 合并多行表格              │
│  ② 自动识别列头              │
│  ③ 提取测试用例字段          │
│  ④ 按编号去重                │
│  ⑤ 过滤低质量用例            │
│  ⑥ 生成统计报告              │
│  ⑦ 构建 XMind XML 结构       │
│  ⑧ 导出 Excel 表格           │
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│  输出:.xmind + .xlsx        │
│  控制台:统计报告             │
└──────────────────────────────┘

步骤 1:知识库检索

python 复制代码
class DifyRetriever:
    def retrieve(self, query: str, top_k: int = 5) -> List[Dict]:
        """检索知识库,返回相关文档块"""
        payload = {
            "retrieval_model": {
                "search_method": "semantic_search",  # 语义搜索
                "top_k": top_k,                      # 返回数量
                "score_threshold_enabled": True,      # 启用阈值过滤
                "score_threshold": 0.6,               # 相似度阈值
            },
            "query": query,
        }
        # 调用 Dify Retrieval API
        resp = self._client.post(
            f"/v1/datasets/{self.dataset_id}/retrieve",
            json=payload,
        )
        # 解析返回结果,按分数降序排列
        results = []
        for record in data.get("records", []):
            segment = record.get("segment", {})
            results.append({
                "content": segment.get("content", ""),
                "score": segment.get("score", 0),
                "title": segment.get("document_name", ""),
            })
        results.sort(key=lambda x: x["score"], reverse=True)
        return results

关键点:

  • 使用 语义搜索semantic_search),而非全文搜索,能理解查询意图
  • 设置 score_threshold: 0.6,过滤掉低相关度结果
  • 结果按相关度降序排列,只取 Top-K 条

步骤 2:LLM 生成

LLM 的 Prompt 由三部分组成:

复制代码
用户 Prompt = 需求描述 + 知识库上下文 + Skill 提示词

系统 Prompt 定义了 LLM 的角色定位:

复制代码
你是一个资深的测试工程师,擅长根据需求文档和业务知识生成高质量的测试用例。

要求:
1. 覆盖正常流程、异常流程和边界场景
2. 测试步骤清晰、可执行
3. 预期结果明确、可验证
4. 按优先级标记:P0(核心功能)、P1(重要功能)、P2(次要功能)

Skill 提示词 是每种测试设计方法的模板。以等价类划分为例:

复制代码
## 【Skill:等价类划分 + 边界值分析】

请使用等价类划分和边界值分析法,对每个输入字段生成测试用例:

### 方法说明
1. 有效等价类:符合需求的有效输入,覆盖正常场景
2. 无效等价类:不符合需求的无效输入,覆盖异常场景
3. 边界值分析:对每个边界(上点、内点、离点)单独测试

### 输出格式(必须严格使用以下6列表格)
| 用例编号 | 测试场景 | 前置条件 | 测试步骤 | 预期结果 | 优先级 |
|---------|---------|---------|---------|---------|-------|
| TC-EP-001 | 有效等价类-正常值 | 输入正常值 | 执行输入校验 | 通过 | P0 |

流式输出 的实现:

python 复制代码
stream = self.client.chat.completions.create(
    model=self.model,
    messages=[...],
    stream=True,  # 启用流式
)
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta and delta.content:
        collected.append(delta.content)
        token_count += 1
        if token_count % 20 == 0:
            print(".", end="", flush=True)  # 每20token打印一个点

步骤 3:解析与输出

这一步是整个方案中最具挑战性的部分,因为 LLM 的输出具有不确定性。

3.1 表格解析的挑战

LLM 输出的 Markdown 表格可能存在以下问题:

问题 示例 解决方案
列头不一致 "前置条件" vs "请求参数" 列头自动映射
列顺序变化 优先级列不在第6列 按列名匹配,不依赖位置
单元格内换行 步骤列有多行内容 多行合并算法
用例重复 多次生成相同用例 按编号去重
无效内容 场景为空、占位符 质量过滤
3.2 列头自动映射
python 复制代码
COLUMN_ALIASES = {
    "id": ["用例编号", "用例id", "编号", "id", "case id", "case_id"],
    "scenario": ["测试场景", "场景", "场景描述", "场景类型", "组合说明", "异常场景"],
    "precondition": ["前置条件", "前置", "前提", "前提条件", "请求参数", "预置条件", "输入值"],
    "steps": ["测试步骤", "步骤", "操作步骤", "测试过程", "执行步骤", "注入方式", "操作"],
    "expected": ["预期结果", "预期", "结果", "期望结果", "预期响应", "预期行为", "响应", "恢复验证", "预期状态码"],
    "priority": ["优先级", "优先", "级别", "等级", "p0", "p1", "p2"],
}

这个映射表覆盖了各种可能的列头写法,即使是英文混写也能正确匹配。

3.3 多行单元格合并

当 LLM 在某个单元格内使用换行时,表格会被拆分成多行。通过比较列数来判断:

python 复制代码
def _merge_multiline_table(markdown_text):
    for line in lines:
        stripped = line.strip()
        is_table_line = stripped.startswith("|")
        if is_table_line:
            cell_count = len([c for c in stripped.split("|")[1:-1] if c.strip()])

        # 列数少于预期 → 续行(合并到上一个单元格)
        # 列数等于预期 → 新行
        if cell_count < expected_cols:
            buffer += " " + stripped  # 续行
        else:
            merged.append(buffer)     # 新行
            buffer = stripped
3.4 XMind 构建

XMind 文件本质上是 ZIP 压缩包,包含 XML 格式的内容文件:

复制代码
output.xmind
├── content.xml          # 思维导图内容(XML)
├── meta.xml             # 元数据(作者信息)
└── META-INF/
    └── manifest.xml     # 文件清单

构建 XML 的层次结构:

复制代码
XMind Topic Tree:
└── 测试用例 (根节点)
    ├── 模块名1 (N用例)
    │   ├── [P0] TC-001 测试场景描述
    │   │   ├── 前置条件: xxx
    │   │   ├── 测试步骤: xxx
    │   │   └── 预期结果: xxx
    │   └── [P1] TC-002 测试场景描述
    └── 模块名2 (N用例)
        └── ...
3.5 Excel 导出

使用 openpyxl 生成带样式的 Excel 表格:

  • 蓝色表头、冻结首行
  • 优先级列着色:P0 红色、P1 橙色、P2 黄色
  • 自动列宽、自动换行

五、Skill 插件系统详解

Skill 是这套方案的核心设计亮点,它让测试设计方法成为可插拔的组件。

基类定义

python 复制代码
class BaseSkill(ABC):
    @property
    @abstractmethod
    def name(self) -> str:
        """Skill 唯一标识"""

    @property
    @abstractmethod
    def description(self) -> str:
        """Skill 描述"""

    @abstractmethod
    def build_prompt_section(self, requirement: str, knowledge: str) -> str:
        """构建该 Skill 对应的 Prompt 片段"""

加载机制

python 复制代码
def load_skills(names: List[str]) -> List[BaseSkill]:
    registry = {
        "equivalence": EquivalenceSkill,
        "scenario": ScenarioSkill,
        "orthogonal": OrthogonalSkill,
        "exception": ExceptionSkill,
        "api": ApiTestSkill,
    }
    return [cls() for name in names if (cls := registry.get(name))]

5 种内置 Skill 详解

Skill 标识 适用场景 典型用例数 示例
等价类划分 equivalence 输入框、表单验证、参数校验 6-10 用户名长度校验
场景法 scenario 业务流程、状态流转、端到端 4-8 订单支付流程
正交实验法 orthogonal 多参数组合、配置项测试 6-15 搜索筛选条件
异常测试 exception 错误处理、系统容错 5-10 网络超时、SQL注入
接口测试 api RESTful API、微服务接口 6-12 用户登录接口

组合使用

Skill 可以自由组合,LLM 会按顺序生成对应的测试用例:

bash 复制代码
# 等价类 + 场景法 → 覆盖输入校验和业务流程
python main.py -r "订单支付" -s equivalence scenario

# 接口测试 + 正交实验法 → 覆盖接口参数和组合
python main.py -r "搜索API" -s api orthogonal

# 全部 Skill 组合 → 全面覆盖
python main.py -r "用户注册" -s equivalence scenario orthogonal exception api

六、使用示例

1. 基本使用

bash 复制代码
python main.py -r "用户登录功能支持用户名密码和验证码登录"

输出:

复制代码
[1/3] 检索知识库...
  检索到 3 条相关文档
[2/3] LLM 生成测试用例...
  生成中: .................... 完成 (420 tokens, 2350 字符)
[3/3] 生成 XMind 文件...
  [XMindGenerator] 解析到 12 个原始用例
  [XMindGenerator] 去重: 移除 1 个重复用例
  [XMindGenerator] 质量过滤: 移除 0 个低质量用例
  [统计] 共 11 个测试用例
    P0(核心): 4 | P1(重要): 5 | P2(次要): 2
  [XMind] 已生成: output/test_cases_abc12345.xmind
  [Excel] 已导出: output/test_cases_abc12345.xlsx

2. 组合多个 Skill

bash 复制代码
python main.py -r "订单支付流程" -s equivalence scenario exception

3. 跳过知识库检索

bash 复制代码
python main.py -r "文件上传功能" --no-retrieve -s equivalence

4. 指定输出路径

bash 复制代码
python main.py -r "登录模块" -o login_test.xmind -k 10

七、项目目录结构

复制代码
testcase_generator/
├── main.py                  # 主入口,编排三步流程
├── config.py                # 全局配置(API Key、模型、参数)
├── dify_retriever.py        # Dify 知识库检索模块
├── llm_client.py            # LLM 客户端(Ollama API,流式输出)
├── xmind_generator.py       # 解析 + 去重 + 生成 XMind + Excel
├── preview_xmind.py         # XMind → HTML 预览工具(浏览器查看)
├── requirements.txt         # 依赖
├── README.md                # 使用文档
├── skills/                  # 测试设计方法(Skill 插件)
│   ├── __init__.py          # BaseSkill 基类 + 加载器
│   ├── equivalence.py       # 等价类划分 + 边界值分析
│   ├── scenario.py          # 场景法(业务流程覆盖)
│   ├── orthogonal.py        # 正交实验法(组合覆盖)
│   ├── exception.py         # 异常/容错测试
│   └── api_test.py          # 接口测试(参数 + 状态码)
└── output/                  # 生成的输出文件
    ├── test_cases_*.xmind
    └── test_cases_*.xlsx

八、环境准备

1. 部署 Dify

bash 复制代码
# 在服务器上部署 Dify 社区版
docker compose up -d
# 访问 http://localhost:8080

2. 部署 Ollama

bash 复制代码
# 安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型
ollama pull deepseek-r1:7b
ollama pull nomic-embed-text

3. 配置 Dify 知识库

  1. 登录 Dify,创建知识库(数据集)
  2. 上传业务文档(PRD、接口文档等)
  3. 选择嵌入模型为 nomic-embed-text
  4. 获取数据集 ID 和 API Key

4. 安装 Python 依赖

bash 复制代码
pip install httpx openai openpyxl

5. 配置

编辑 config.py

python 复制代码
DIFY_API_KEY = "dataset-xxx"              # 从 Dify 获取
DATASET_ID = "xxx"                         # 知识库数据集 ID
DIFY_BASE_URL = "http://localhost:8080"    # Dify 服务地址
OLLAMA_BASE_URL = "http://localhost:11434" # Ollama 服务地址
LLM_MODEL = "deepseek-r1:7b"              # 生成模型

九、总结与展望

已实现的功能

  • ✅ 自动检索 Dify 知识库,获取业务文档上下文
  • ✅ 5 种测试设计方法(等价类、场景法、正交实验法、异常测试、接口测试)
  • ✅ Skill 插件机制,可自由组合和扩展
  • ✅ 流式输出,实时显示生成进度
  • ✅ 表格解析容错(列头自动映射、多行合并)
  • ✅ 用例去重 + 质量过滤
  • ✅ 同时输出 XMind 思维导图 + Excel 表格
  • ✅ 统计报告(P0/P1/P2 分布、模块分布)

可扩展的方向

  • 更多 Skill:可以继续添加决策表测试、状态迁移测试、性能测试等
  • 多轮对话:对生成的用例进行追加、修改、补充
  • 批量生成:从需求文档中自动提取多个需求点,批量生成
  • 测试用例管理:对接 TestLink、Jira 等测试管理平台
  • Web 界面:提供简单的 Web 操作界面,降低使用门槛

项目地址:可直接在本地部署使用

如果你也在做测试提效相关的工作,欢迎交流讨论!

相关推荐
文心快码BaiduComate1 小时前
从“代码补全”到“自主交付”:文心快码全私有化部署落地中信百信银行核心研发链路
人工智能·程序员·文心快码
__如果1 小时前
Medical Benchmark
人工智能
β添砖java1 小时前
深度学习32Transformer、BERT、
人工智能·深度学习
SomeBottle1 小时前
【小记】图片托管从又拍云迁移到腾讯云 EO + COS(兼容图片处理参数)
python·计算机网络·学习笔记·对象存储·cdn·折腾
2601_962387821 小时前
学习笔记DAY1:Python编程从0开始学起,从自学入门到精通
人工智能·网络爬虫·学习笔记·网页开发·python编程
TechEdu2026062 小时前
[人工智能]AI芯片家族:英伟达、AMD、英特尔、高通与华为
人工智能·ai
具身AGI2 小时前
物理AI人类学习路线的答案
人工智能·学习
johnsong2 小时前
AI前沿日报 2026-09-06
人工智能
海鸥812 小时前
AIOps(智能运维)理解
运维·人工智能