Files
yixiong-claude-marketplace/plugins/zentao/skills/zentao-test/SKILL.md
T
SkyJourneyandClaude Sonnet 5 9d9e31c98e [feat] Add zentao plugin (Claude Code + Codex dual scaffold)
新增禅道项目管理系统插件,含项目集/产品/项目/执行、需求
(story/epic/requirement)、Bug、任务、测试、计划与发布、反馈工单
八个工作流技能,自动配置 MCP 连接(禅道「个人中心 → 获取凭证」
自助生成 14 天 Token)。

MCP Server 是团队自建的 zentao-mcp 网桥(部署在
pm.ops.yixiong-tech.com/mcp),基于开源 openapi-mcp-server 二次开发。
Claude 侧走 userConfig 钥匙链 + 自定义 token 头;Codex 侧受限于官方
插件格式只支持 bearer_token_env_var,走 Authorization: Bearer——网桥
那边已经加了 preferred_header/bearer_mode 配置项统一归一化处理,两条
路径都验证过连通。

三轮审查(静态字段对照 openapi.json、跨文件一致性、真实端点实测)
修正过程中发现的问题,技能文档里引用的工具名全部跟服务器真实注册
的 118 个工具核对过。

同步更新:.claude-plugin/marketplace.json、.agents/plugins/marketplace.json、
README.md、CLAUDE.md 的插件索引与说明;README 补充「获取凭证」操作
截图(已脱敏)。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pFx6jnym6kRWRQ5JyDUNv
2026-08-25 13:50:41 +08:00

123 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: zentao-test
description: "禅道测试管理:创建/查询/修改测试用例(含步骤设计)、创建测试单提测。当用户说「写个测试用例」「设计测试步骤」「提测」「建个测试单」「查测试用例」时使用。"
---
# 禅道测试管理(testcase / testtask
**前置:先读 `zentao-shared`(尤其"路径参数不出现在 inputSchema 里"一节)。**
测试相关是高频场景——测试同学写用例、开发/测试提测,这个技能覆盖得比其他业务域更细,
尤其是 testcase 的步骤结构,是全部 8 个技能里**唯一一处需要特别小心的嵌套/对应关系**。
---
## 测试用例(testcase
### 详情接口的路径参数命名例外(跟 zentao-story 的 storyID 是同类坑)
```
get_testcases_caseID(caseID) 详情:参数字面叫 caseID
put_testcases_testcasID(...) 修改:参数字面叫 testcasID(注意,是 testcasID 不是 testcaseID,少一个 e
delete_testcases_testcasID(...) 删除:同上
```
三个接口的路径参数名互相都不一样(`caseID` / `testcasID`),且 `testcasID` 是官方 API
的拼写(缺了一个 `e`),**照抄字面参数名,不要自己纠正拼写**,传错名字会静默返回空结果。
### 查
```
get_products_productID_testcases(productID, ...)
get_projects_projectID_testcases(projectID, ...)
get_executions_executionID_testcases(executionID, ...)
get_testcases_caseID(caseID) 详情
```
### 建——步骤是三个平行数组,靠索引位置对应
```
post_testcases({ payload: {
productID, title,
module?, story?, pri?, type?, precondition?,
steps?: string[], # 步骤描述,第 i 项
expects?: string[], # 第 i 项步骤的期望结果
stepType?: string[], # 第 i 项步骤的类型:step 步骤 | group 父级步骤(分组标题,无需期望结果)
project?, execution?
} })
```
**这不是一个"步骤对象数组"(不是 `[{step, expect, type}, ...]`),是三个独立的字符串
数组,`steps[i]`/`expects[i]`/`stepType[i]` 靠同一个下标 `i` 对应同一个步骤。** 三个
数组长度必须一致,写用例时先把步骤列成一个表格跟用户确认,再按顺序拆成三个数组传,
不要把某一步的期望结果错位对到别的步骤上——这种错位不会报错,只会在用例详情里显示
"驴唇不对马嘴",很难事后发现。
`stepType``group` 的行是分组标题(比如"登录流程"这种大标题),对应的 `expects[i]`
一般传空字符串。
举例——"登录"用例有一个分组、两个步骤:
```
steps = ["登录流程", "打开登录页,输入正确账号密码", "点击登录按钮"]
stepType = ["group", "step", "step"]
expects = ["", "账号密码输入框正常显示", "跳转到首页,显示欢迎语"]
```
`type`(用例类型)受限枚举:`unit` 单元测试 | `interface` 接口测试 | `feature` 功能测试 |
`install` 安装部署 | `config` 配置相关 | `performance` 性能测试 | `security` 安全相关 |
`other` 其他。
### 改 / 删
```
put_testcases_testcasID({ testcasID, payload: {...} }) # 改步骤同样是三个数组整体替换,不是增量
delete_testcases_testcasID({ testcasID })
```
改步骤时**传的是完整的三个新数组,不是"追加一步"**——想加一个步骤,要先 `get_testcases_caseID`
拿到现有的 steps/expects/stepType,在末尾追加后整体传回,跟 `huanxi-task`
`task_set_assignees` 整组覆盖是同一种坑,直接传一步会把其余步骤全部覆盖掉。
---
## 测试单(testtask,提测)
**没有单条测试单详情接口**(只有创建/修改/删除,没有 `get_testtasks_testtaskID`),要看
某个测试单的信息,从列表接口里按 ID 过滤。
### 查
```
get_products_productID_testtasks(productID, ...)
get_projects_projectID_testtasks(projectID, ...)
get_executions_executionID_testtasks(executionID, ...)
```
### 建
```
post_testtasks({ payload: { productID, name, build, begin, end, execution?, type?,
owner?, status?, desc? } })
```
`productID`/`name`/`build`(提测构建/版本)/`begin`/`end` 必填。
**`type`(测试类型)是字符串数组,不是单值**——一个测试单可以同时标多种测试类型,取值
受限:`integrate` 集成测试 | `system` 系统测试 | `acceptance` 验收测试 | `performance` 性能测试
| `safety` 安全测试。传的时候是 `type: ["integrate", "system"]` 这种数组形式,不要传成
单个字符串 `type: "integrate"`
**跟其他实体不同,测试单的状态不是靠专门的 activate/close 端点切换,而是创建/修改时
直接传 `status` 字段**`wait` 未开始 | `doing` 进行中 | `done` 已关闭 | `blocked` 被阻塞。
改状态就是 `put_testtasks_testtaskID({ testtaskID, payload: { status: "doing" } })`
### 改 / 删
```
put_testtasks_testtaskID({ testtaskID, payload: {...} })
delete_testtasks_testtaskID({ testtaskID })
```
删除不可逆,执行前必须确认。