
这次我们直接切入一个 AI 工程化里越来越痛的问题Agent 的 Skills 到底怎么测很多团队做 Agent 开发时Skill 写了一大堆跑起来也像模像样但一上线就出问题。要么 Skill 在独立调用时正常放进 Agent 工作流里就抽风要么大模型返回的结果格式时好时坏手工点几轮没问题一到批量任务就翻车。原因很简单Skills 是给 LLM 用的函数但它本质还是代码代码就要测试而且不能只测一种维度。这篇文章不聊概念只讲三套能落地的测试方案Pytest 单元测试、LLM/LVM 自动评价、Agent 集成测试。每一套都会给出环境、代码、运行方式和验证标准你能直接抄进自己的项目里。核心关注点有三个怎么用 Pytest 把 Skill 的纯逻辑测清楚怎么引入 LLM 和 LVM 当“自动阅卷老师”检查多模态输出质量怎么在完整 Agent 调用链里验证 Skill 是否被正确触发和返回。读者对象是正在做 AI Agent 开发、Skill 中间件封装或 LLM 应用测试的工程师。如果你团队里已经有“Skill 写了没人敢改”的问题这篇文章建议直接收藏。1. Skill 测试三大方案核心能力速览先给一张总表把三套方案分别解决什么问题、需要什么工具、成本高不高说清楚。测试方案核心定位主要工具验证目标成本与门槛方案一Pytest 单元测试验证 Skill 的确定性逻辑Pytest、pytest-asyncio、pytest-cov输入输出格式、边界条件、异常处理、纯函数正确性低CPU 即可运行速度快方案二LLM/LVM 自动评价验证 Skill 与大模型协作后的输出质量LLM API、LVM 多模态模型、结构化评测脚本输出是否符合指令、是否包含关键字段、多模态内容是否准确中需要 API 额度或本地模型结果有概率波动方案三Agent 集成测试验证 Skill 在真实调用链中的行为Agent 框架、Mock 工具、端到端测试脚本Skill 是否被正确触发、参数传递是否正确、异常是否被兜底高需要完整运行环境耗时较长三套方案不是替代关系而是分层关系。Pytest 管“代码正确性”LLM/LVM 评价管“输出合理性”Agent 集成测试管“链路稳定性”。三套都做齐Skill 才算真正有质量保障。方案二里需要多说一句 LVM 和 LLM 的区别。LLM 处理的是文本输入输出负责理解指令、生成结构化内容LVMLarge Vision Model大视觉模型则能直接接收图片、视频等视觉输入在图生文、图片理解、视觉问答这类任务上表现更强。如果你们的 Skill 涉及图像分析、文档 OCR、截图理解那么方案二的评测模型优先考虑 LVM如果只是纯文本生成LLM 就够用。2. Skill 测试适用场景与合规边界2.1 适合谁用这套测试体系并不是所有项目都需要全套上马按阶段选择即可个人开发者或小团队如果 Skill 数量少于 10 个建议先跑方案一。保证每个 Skill 的纯逻辑不出错已经能规避大部分低级故障。中大型 Agent 项目Skill 数量多、相互依赖复杂必须叠加方案三。尤其是多个 Skill 共享上下文、交叉调用的时候单测覆盖不到的集成问题会集中爆发。对外提供 API 服务的团队方案二建议长期运行。因为外部用户会输入各种意想不到的文本和图片LLM/LVM 评价能帮你提前拦截“答非所问”和“格式不符合要求”的输出。2.2 不适合什么场景不是所有环节都适合自动化测试。比如非常依赖 LLM 随机创造力的功能像头脑风暴、开放式文案生成用固定评测标准去打分反而会误伤。这种场景应该用人工抽检。延迟极其敏感的服务方案二和方案三会引入模型推理时间不适合放在请求链路的同步环节里做实时校验。尚未稳定的原型阶段如果 Skill 的输入输出协议还在频繁变动先别急着写测试否则每改一次接口就要重写一批用例。2.3 使用边界与合规提醒涉及 LLM/LVM 测试有几点必须反复强调数据隐私生产环境的用户输入可能包含个人信息、商业机密。评测数据要先做脱敏处理原则上不允许直接把真实用户数据发送给第三方模型 API。版权授权如果 Skill 是图像生成、音色克隆、视频处理类测试素材必须确认版权归属。拿他人作品当测试集风险很高。模型输出不可控LLM/LVM 的判定结果天然带有概率性。评测失败不代表功能一定坏要结合日志和人工复核不能盲目用模型评价结果去卡发布流程。安全边界不要用测试代码去尝试绕过模型的内容安全策略。测试目标是验证功能符合预期不是攻击模型。3. Skill 测试环境准备与前置条件在写测试代码之前先把环境准备好。这里给出一个经过验证的通用配置思路。3.1 操作系统与 Python 版本建议使用 Linux 或 macOS 作为开发和 CI 运行环境。Windows 也可以跑但遇到 asyncio 事件循环和模型 SDK 时偶尔会有进程管理上的差异。Python 版本建议 3.10 及以上。原因是 AI Agent 相关框架对 3.10 的支持最稳定类型注解语法也更完整。3.2 Python 依赖清单创建虚拟环境后安装下面这些依赖python -m venv .venv source .venv/bin/activate # 核心测试框架 pip install pytest pytest-asyncio pytest-cov # HTTP 请求与 API 调用 pip install requests # 结构化输出校验可选 pip install pydantic # Agent 测试的 Mock 工具按实际框架选择 pip install unittest-mock # 或者使用内置 unittest.mock如果项目里已经用了某一款 Agent 框架比如 OpenAI SDK、LangChain、Claude Agent SDK 等把对应 SDK 也装上。本文的示例代码不绑定具体 Agent 框架会以 pytest requests 作为基础演示。3.3 环境变量配置模型 API 的 Key 不要写死在代码里。建议统一放在.env文件并用环境变量读取。# .env 示例 LLM_API_KEYyour_llm_api_key LLM_BASE_URLhttps://api.example.com/v1 LVM_API_KEYyour_lvm_api_key LVM_BASE_URLhttps://api.example.com/v1在测试代码中加载import os from dotenv import load_dotenv load_dotenv() LLM_API_KEY os.getenv(LLM_API_KEY) LLM_BASE_URL os.getenv(LLM_BASE_URL)这样做的好处是CI 里不用改代码只需要注入环境变量。3.4 项目目录结构推荐按下面的结构组织项目能让测试文件和被测代码清晰分离。skill_project/ ├── skills/ # Skill 核心实现 │ ├── __init__.py │ ├── image_skill.py # 示例图像信息提取 Skill │ └── text_skill.py # 示例文本摘要 Skill ├── tests/ # 测试文件目录 │ ├── __init__.py │ ├── conftest.py # pytest 全局配置 │ ├── test_image_skill_unit.py # 方案一单元测试 │ ├── test_text_skill_unit.py │ ├── eval_llm.py # 方案二LLM/LVM 评价 │ ├── eval_lvm.py │ ├── test_agent_integration.py # 方案三Agent 集成测试 │ └── data/ # 测试输入素材 │ ├── sample_image.jpg │ └── sample_text.txt ├── .env ├── requirements.txt └── pyproject.toml4. Skill 测试项目搭建从一个示例 Skill 开始为了把三套方案讲清楚这里先构造一个可运行的示例 Skill。它能调用多模态模型从一张商品图片中提取信息并返回结构化 JSON。这个 Skill 同时涉及 LLM 和 LVM用来演示测试方案非常合适。4.1 Skill 实现示例# skills/image_skill.py 图像信息提取 Skill。 输入图片路径 输出结构化商品信息包括名称、颜色、品牌、标签 import json from typing import Dict, Any import requests class ImageInfoSkill: def __init__(self, base_url: str, api_key: str): self.base_url base_url self.api_key api_key def extract_info(self, image_path: str, prompt: str ) - Dict[str, Any]: 调用 LVM 模型从图片中提取结构化信息。 if not image_path: raise ValueError(image_path cannot be empty) # 实际项目中这里换成对应 LVM SDK 的调用方式 response requests.post( f{self.base_url}/v1/vision/extract, headers{Authorization: fBearer {self.api_key}}, json{ image_path: image_path, prompt: prompt, }, timeout60, ) response.raise_for_status() result response.json() # 对返回内容做基础格式校验 return self._normalize_output(result) staticmethod def _normalize_output(raw: Dict[str, Any]) - Dict[str, Any]: 统一返回 JSON 结构保证键名和类型一致。 required_keys [name, color, brand, tags] normalized { name: raw.get(name, ), color: raw.get(color, ), brand: raw.get(brand, ), tags: raw.get(tags, []), } # tags 必须是列表 if not isinstance(normalized[tags], list): normalized[tags] [] return normalized def validate_result(self, data: Dict[str, Any]) - bool: 校验结构化输出是否满足要求。 if not isinstance(data, dict): return False if not data.get(name): return False if not isinstance(data.get(tags), list): return False return True这个 Skill 的输入输出协议很清晰输入图片路径输出{name, color, brand, tags}四个字段。接下来三套测试都围绕它展开。5. 方案一Pytest 单元测试 Skill 的确定性逻辑5.1 测试目标单元测试的目标是“不依赖真实模型验证代码本身的正确性”。我们把 Skill 拆成两个部分来测对空输入、非法输入的异常处理。对模型返回结果的标准化和校验逻辑。真实 HTTP 调用必须被 Mock 掉这样才能保证测试速度快、可重复。5.2 编写 Mock 测试使用 pytest unittest.mock 实现# tests/test_image_skill_unit.py import json import pytest from unittest.mock import patch, Mock from skills.image_skill import ImageInfoSkill pytest.fixture def skill(): 构造不带真实 API Key 的 Skill 实例。 return ImageInfoSkill( base_urlhttp://mock.example.com, api_keytest-key, ) def test_extract_info_success(skill): 测试正常流程模型返回合法数据。 mock_response Mock() mock_response.json.return_value { name: 无线蓝牙耳机, color: 白色, brand: TestBrand, tags: [耳机, 蓝牙, 白色], } mock_response.raise_for_status.return_value None with patch(skills.image_skill.requests.post, return_valuemock_response): result skill.extract_info(data/sample_image.jpg) assert result[name] 无线蓝牙耳机 assert result[color] 白色 assert isinstance(result[tags], list) assert len(result[tags]) 3 def test_extract_info_empty_path(skill): 测试异常分支图片路径为空。 with pytest.raises(ValueError): skill.extract_info() def test_normalize_output_missing_keys(skill): 测试模型返回字段缺失时normalize 能补齐默认值。 raw { name: 杯子, color: 蓝色, } result skill._normalize_output(raw) assert result[brand] assert result[tags] [] def test_validate_result_reject_invalid(skill): 测试校验函数能识别非法输出。 invalid_data {name: , tags: not-a-list} assert skill.validate_result(invalid_data) is False5.3 运行方式pytest tests/test_image_skill_unit.py -v --covskills预期输出类似tests/test_image_skill_unit.py::test_extract_info_success PASSED tests/test_image_skill_unit.py::test_extract_info_empty_path PASSED tests/test_image_skill_unit.py::test_normalize_output_missing_keys PASSED tests/test_image_skill_unit.py::test_validate_result_reject_invalid PASSED5.4 方案一成功标准全部用例通过。代码覆盖率报告里skills/image_skill.py的关键分支都被覆盖。不发起真实网络请求执行时间在几秒内。这一层跑通说明 Skill 的纯逻辑是稳的。但单元测试有个盲区它只验证了“模型返回合法数据时我们的处理逻辑正确”没验证“真实模型会不会返回合法数据”。这就是方案二要解决的问题。6. 方案二LLM/LVM 自动评价 Skill 输出质量6.1 测试目标方案二不再 Mock 模型而是真实调用 LLM 或 LVM让大模型对 Skill 的输出进行评价。这里的关键是设计一套让模型能“客观”打分的评测标准。理论上我们完全可以用人工去看几十张图片的提取效果。但批量任务几百上千条的时候人工不现实必须用模型当自动阅卷老师。6.2 设计评测 prompt这里有一个实战经验评测 prompt 必须比业务 prompt 更严格。要求大模型输出 JSON 结构并强制给出“通过/不通过”和“原因”。# tests/eval_lvm.py import json import requests def build_eval_prompt(image_path: str, extracted_result: dict) - list: 构造 LVM 评测 prompt。 参数说明 image_path: 原始测试图片路径 extracted_result: Skill 从图片中提取出的结构化信息 system_prompt ( 你是一个严谨的视觉信息评测员。 你需要查看原始图片并判断给定的结构化信息是否准确。 只输出 JSON不要输出多余文字。 ) user_prompt { task: 请对比以下从商品图片中提取的信息是否准确。, image_path: image_path, extracted_info: extracted_result, eval_rules: [ 如果名称、颜色、品牌、标签任一字段明显错误结论为不通过。, 如果标签缺失关键属性结论为不通过。, 如果信息和图片完全一致结论为通过。, ], output_format: { passed: boolean, reason: string, 不超过50字 } } return [ {role: system, content: system_prompt}, {role: user, content: json.dumps(user_prompt, ensure_asciiFalse)}, ] def call_lvm_eval(base_url: str, api_key: str, image_path: str, extracted_result: dict) - dict: 调用 LVM 模型执行评测。 messages build_eval_prompt(image_path, extracted_result) response requests.post( f{base_url}/v1/vision/eval, headers{Authorization: fBearer {api_key}}, json{ model: lvm-eval-model, messages: messages, }, timeout120, ) response.raise_for_status() return response.json()6.3 批量评测脚本实际项目中方案二通常不在 pytest 里跑而是单独作为一个评测脚本因为要控制 API 成本和耗时。# tests/eval_llm.py 批量评测 Skill 输出并输出统计报告。 import json import os from typing import List, Dict import requests from skills.image_skill import ImageInfoSkill def load_test_cases(test_file: str) - List[Dict]: 读取测试用例。测试用例文件格式为 JSON List。 with open(test_file, r, encodingutf-8) as f: return json.load(f) def run_evaluation(): base_url os.getenv(LVM_BASE_URL) api_key os.getenv(LVM_API_KEY) skill ImageInfoSkill(base_urlbase_url, api_keyapi_key) # 测试用例实际项目中每个用例包含图片路径和期望字段 test_cases [ {image_path: data/sample_image.jpg, expected_tags: [耳机, 蓝牙]}, {image_path: data/sample_cup.jpg, expected_tags: [杯子]}, ] results [] for case in test_cases: extracted skill.extract_info(case[image_path]) eval_result call_lvm_eval(base_url, api_key, case[image_path], extracted) results.append({ case: case, extracted: extracted, eval: eval_result, }) # 统计通过率 passed sum(1 for r in results if r[eval].get(passed) is True) total len(results) print(f评测完成通过 {passed}/{total}通过率 {passed / total * 100:.1f}%) # 输出详细结果到文件 with open(eval_report.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) if __name__ __main__: run_evaluation()6.4 方案二成功标准批量评测脚本可稳定运行默认测试集通过率不低于团队设定的阈值。评测报告能明确指出哪些图片提取失败、失败原因是什么。同一批数据多次评测结果波动在可接受范围内如果波动过大优先检查评测 prompt 是否写清楚了。这里要特别提醒LLM/LVM 评测结果天然有随机性。同一个输出用不同模型、不同温度参数评分结果可能不一样。建议在评测请求里固定temperature0尽可能降低随机性。7. 方案三Agent 集成测试验证完整调用链7.1 测试目标前面两套方案验证了“Skill 本身正确”和“Skill 输出质量合格”。但真正上线时Skill 是在 Agent 的完整调用链中运行的流程是用户输入 - Agent 理解意图 - 选择 Skill - 传参调用 - 拿结果回填 - 生成最终回复这个链路中经常出现的问题有Agent 没有在应该调用 Skill 的时候调用它。调用 Skill 时传参错误比如把图片路径传成了文本。Skill 返回了异常但 Agent 没有兜底处理直接把错误暴露给用户。方案三要验证的正是这些链路问题。7.2 集成测试代码示例这里不绑定具体 Agent 框架用一个简化版的自定义 Agent 引擎来演示。实际项目中把agent.run()换成你们自己的入口即可。# tests/test_agent_integration.py Agent 集成测试验证 Agent 能否正确调用 ImageInfoSkill。 import os import pytest from unittest.mock import patch, Mock from skills.image_skill import ImageInfoSkill class SimpleAgent: 简化版 Agent 引擎。 真实项目中这里是你们的 Agent 执行流程 支持意图识别、Skill 选择、参数注入、结果回填。 def __init__(self, skill: ImageInfoSkill): self.skill skill def handle_request(self, user_input: str, image_path: str None): 处理用户请求。 模拟 1. 如果输入中包含“提取”关键词调用 image skill。 2. 如果调用失败返回兜底话术。 if 提取 in user_input and image_path: try: result self.skill.extract_info(image_path) return {success: True, data: result} except Exception as e: return {success: False, error: str(e)} return {success: False, error: no skill matched} pytest.fixture def agent(): skill ImageInfoSkill( base_urlhttp://mock.example.com, api_keytest-key, ) return SimpleAgent(skill) def test_agent_calls_skill_when_input_matches(agent): 验证用户输入包含关键词时Agent 应该触发 Skill。 mock_response Mock() mock_response.json.return_value { name: 无线蓝牙耳机, color: 白色, brand: TestBrand, tags: [耳机, 蓝牙], } mock_response.raise_for_status.return_value None with patch(skills.image_skill.requests.post, return_valuemock_response): result agent.handle_request(帮我提取图片信息, data/sample_image.jpg) assert result[success] is True assert result[data][name] 无线蓝牙耳机 def test_agent_does_not_call_skill_when_input_not_match(agent): 验证用户输入不包含触发词时Agent 不应调用 Skill。 result agent.handle_request(你好, data/sample_image.jpg) assert result[success] is False assert result[error] no skill matched def test_agent_handles_skill_exception(agent): 验证Skill 抛异常时Agent 能返回兜底错误而不是直接崩溃。 with patch( skills.image_skill.requests.post, side_effectException(network error), ): result agent.handle_request(帮我提取图片信息, data/sample_image.jpg) assert result[success] is False assert network error in result[error]7.3 真实环境集成测试Mock 版集成测试通过后还需要跑一轮“真实环境不 Mock”的集成测试。方法很简单单独建一个 pytest 标记只有显式指定时才运行。pytest tests/test_agent_integration.py -m real_api标记的定义放在pyproject.toml或pytest.ini里# pytest.ini [pytest] markers real_api: 标记需要真实调用模型 API 的集成测试测试代码中加装饰器import pytest pytest.mark.real_api def test_agent_with_real_model(): # 这里是真实调用 LVM 的用例 pass7.4 方案三成功标准所有 Mock 集成测试通过说明 Agent 的调用逻辑正确。真实 API 集成测试通过说明模型返回结果能被 Agent 正确消化。人为制造异常比如断网、超时时Agent 能返回兜底信息不会挂死。8. 把三套方案接进 CI 与批量任务8.1 分层执行策略真实项目里三套方案的执行频率不一样触发时机执行内容原因每次提交代码方案一 Pytest 单元测试速度最快能第一时间发现代码逻辑问题每天定时任务方案二 LLM/LVM 评测消耗 API 额度不需要每次提交都跑发版前 / 每轮迭代方案三 Agent 集成测试链路完整但耗时较长适合在发版前统一跑8.2 GitHub Actions 示例# .github/workflows/skill-test.yml name: Skill Test Pipeline on: push: branches: [main] pull_request: branches: [main] jobs: unit-test: runs-on: ubuntu-latest steps: - name: 拉取代码 uses: actions/checkoutv4 - name: 安装 Python uses: actions/setup-pythonv5 with: python-version: 3.11 - name: 安装依赖 run: | pip install pytest pytest-asyncio pytest-cov requests python-dotenv - name: 运行单元测试 run: | pytest tests/test_*_unit.py -v --covskills eval-test: runs-on: ubuntu-latest needs: unit-test if: github.event_name schedule env: LVM_API_KEY: ${{ secrets.LVM_API_KEY }} LVM_BASE_URL: ${{ secrets.LVM_BASE_URL }} steps: - name: 拉取代码 uses: actions/checkoutv4 - name: 安装 Python uses: actions/setup-pythonv5 with: python-version: 3.11 - name: 安装依赖 run: | pip install pytest requests python-dotenv - name: 运行 LVM 评测 run: | python tests/eval_lvm.py这套流水线把“快速校验”和“深度评测”分开不会因为等模型 API 响应而拖慢开发流程。8.3 批量任务设计建议如果测试用例数量达到几百上千条批量评测任务要关注以下几点控制并发LLM/LVM API 都有速率限制评测脚本要支持限流。可以用threading.Semaphore或者信号量控制同时发出的请求数。失败重试网络抖动导致单条评测失败时不要直接判失败先重试 2 到 3 次。结果落盘每条评测结果都要写入 JSONL 或数据库方便追溯失败样本。进度条显示用tqdm显示批量任务进度避免任务看起来像卡死。# 批量评测时控制并发和重试的示例 import time from concurrent.futures import ThreadPoolExecutor, as_completed import threading semaphore threading.Semaphore(5) # 最多 5 个并发请求 def safe_eval(item): with semaphore: for attempt in range(3): try: return call_lvm_eval( base_url, api_key, item[image_path], item[extracted] ) except Exception as e: if attempt 2: return {passed: False, reason: fretry failed: {e}} time.sleep(2)9. Skill 测试资源占用与性能观察9.1 各方案耗时对比从实际工程角度看三套方案的耗时差异很大方案耗时量级主要消耗资源Pytest 单元测试秒级CPU几乎无内存压力LLM/LVM 评测分钟到小时级网络带宽、API 额度、少量 CPUAgent 集成测试分钟级CPU、内存真实模型时消耗 API 额度9.2 如何观察性能瓶颈单元测试阶段用pytest --durations10查看最慢的 10 个用例。如果某个用例耗时异常优先检查是否有真实网络请求被误放行。LLM/LVM 评测阶段主要观察 API 响应时间和重试率。如果响应时间很长考虑缩小评测 prompt或者换更快的小模型先做一轮初筛。Agent 集成测试阶段重点观察显存和内存。如果 Agent 里加载了本地 LVM 模型显存占用会明显上升。建议用nvidia-smi -l 5实时监控显存变化。关于显存占用这里不做具体数值断言因为不同的 LVM 模型参数量差异很大。一个可靠的做法是在自己机器上跑一轮真实 API 集成测试用nvidia-smi记录峰值显存再根据这个基准给 CI 机器评估是否够用。10. Skill 测试常见问题与排查方法问题现象可能原因排查方式解决方案pytest 报错找不到模块skillsPYTHONPATH 未包含项目根目录检查 pytest 运行路径和项目结构在pyproject.toml中配置pythonpath [.]或使用python -m pytest运行Mock 不生效测试发了真实请求patch 的目标路径写错确认被测试代码里 import 的方式patch 应作用于skills.image_skill.requests.post不是requests.postLVM 评测结果不稳定评测 prompt 不明确或 temperature 过高检查评测配置对比多次结果固定 temperature0在 prompt 中明确列出判定规则Agent 没有触发 Skill意图识别规则没匹配上查看 Agent 日志确认用户输入调整触发条件增加同义词和相似表达批量评测任务卡住并发过高触发限流或单条请求超时未处理查看日志中超时记录设置请求超时时间增加失败重试降低并发数单元测试通过但线上效果差测试数据与实际数据分布不一致检查测试集是否过于理想化增加边界样本、噪声样本、异常格式样本模型返回字段缺失模型输出不符合预期结构打印原始返回 JSON在 Skill 中增加_normalize_output做兜底测试中覆盖缺失字段场景显存不足导致集成测试崩溃本地 LVM 模型占用过高用 nvidia-smi 查看显存换更小模型或改成调用远端模型 API11. Skill 测试最佳实践与工程建议11.1 先把 Skill 做成“纯函数”这是最核心的一条建议。Skill 内部不要直接依赖全局变量、Session 状态或外部服务。把所有外部依赖通过构造函数传进去这样单元测试才能方便 Mock。# 推荐外部依赖通过参数注入 class ImageInfoSkill: def __init__(self, base_url: str, api_key: str): ... # 不推荐在 Skill 内部直接创建 Session class ImageInfoSkillBad: def __init__(self): self.session requests.Session() self.api_key hardcoded-key11.2 固定评测集方案二和方案三的测试集要作为“黄金数据集”维护。每次调整 Skill、更换模型、修改 prompt 后都要用同一份测试集回评才能横向对比效果。测试集不要频繁变动新增测试用例时要记录原因。11.3 分层报告三套方案的结果要汇总成一份分层报告第一层是单元测试通过率第二层是模型评测通过率第三层是集成测试通过率。哪个环节掉链子就聚焦哪个环节排查。这样不会在“模型输出不好”和“代码有 bug”之间来回扯皮。11.4 测试数据脱敏所有测试素材必须先做脱敏。商品图片如果包含人脸、车牌、地址等信息要打码或替换成公开可商用的图片素材。尤其在多人协作团队中测试数据会传播到 CI 日志、评测报告、模型服务端风险面很大。11.5 合规红线凡是涉及人脸、声音、版权素材的 Skill测试用例必须确认授权。不要为了“提高覆盖率”就随意引入他人作品作为测试样本。建议在项目 README 中单独写一节“测试素材授权清单”明确每份测试素材的来源和授权情况。12. 总结与下一步Skill 测试不是可有可无的锦上添花而是 Agent 工程化的必答题。三套方案的落地顺序很清晰第一步把 Skill 的纯逻辑接到 Pytest 单元测试里先保证最快反馈。第二步引入 LLM/LVM 作为自动评测器建立固定评测集和评测报告。第三步在 Agent 完整链路里跑集成测试覆盖触发条件、参数传递、异常兜底。建议第一次接入时先拿一个业务价值最高的 Skill 做试点三套方案都跑通后再横向推广到其他 Skill。最容易踩的坑有两个一是 Mock 目标路径写错导致测试变成真实请求二是评测集没有固定导致不同版本之间无法横向对比。这两点提前避开后面会顺畅很多。下一步可以延伸的方向是把方案二中的 LLM/LVM 评测结果接入可视化看板按时间维度展示 Skill 质量趋势或者把批量评测脚本包装成内部工具让非测试岗位的同事也能提交评测任务。Skill 测试做扎实之后你会发现 Agent 上线的信心会明显不一样。