快速参考指南,帮助 AI 助手高效调用禅道 API
python
from pathlib import Path
import sys
# 导入禅道客户端
lib_path = Path(__file__).parent.parent / 'lib'
sys.path.insert(0, str(lib_path))
from zentao_client import ZenTaoClient, read_credentials
# 读取凭证
credentials = read_credentials()
# 创建客户端
client = ZenTaoClient(
credentials['endpoint'],
credentials['username'],
credentials['password']
)
# 获取会话(首次登录,后续自动加载持久化的 Session)
sid = client.get_session()
客户端自动管理 Session,无需每次都登录:
python
# 首次调用自动登录并保存 Session
sid = client.get_session()
# 新实例自动加载已有 Session
client2 = ZenTaoClient(credentials['endpoint'], credentials['username'], credentials['password'])
sid2 = client2.get_session() # 直接加载,无需登录
# 强制刷新 Session
client.get_session(force_refresh=True)
# 清除保存的 Session
client.clear_session()
存储位置:项目根目录 .zentao/sessions/
python
# 查看我的任务
success, tasks = client.get_my_tasks("assignedTo")
# 查看我的Bug
success, bugs = client.get_my_bugs("assignedTo")
# 查看产品列表
success, products = client.get_products()
# 查看项目列表
projects = client.get_project_list_old("all")
# 查看项目任务
tasks = client.get_project_tasks_old(project_id, "all")
角色API场景全员get_my_tasks("assignedTo")查看指派给我的任务全员get_my_bugs("assignedTo")查看指派给我的Bug研发start_task(task_id)开始任务研发record_estimate(task_id, records)记录工时研发finish_task(task_id)完成任务测试create_bug(...)创建Bug测试resolve_bug(bug_id, ...)解决Bug
角色API场景产品create_story(...)创建需求项目经理create_subtasks(...)创建子任务项目经理assign_task(task_id, user)指派任务全员get_task_detail(task_id)查看任务详情全员get_bug(bug_id)查看Bug详情测试close_bug(bug_id)关闭Bug研发pause_task(task_id)暂停任务
角色API场景产品create_product(...)创建产品产品get_products()查询产品列表产品create_plan(...)创建发布计划项目经理create_project(...)创建项目项目经理get_project(project_id)查询项目详情项目经理start_project(...)启动项目项目经理get_project_list_old()查询项目列表项目经理get_project_tasks_old()查询项目任务测试create_testcase(...)创建测试用例测试create_testtask(...)创建测试任务
python
# ========== 需求管理 ==========
# 创建需求
success, result = client.create_story(
product_id="1",
title="用户登录功能",
pri="3", # 优先级: 0-4
estimate="8", # 预计工时
spec="实现用户登录功能",
reviewer="admin"
)
# 查看我的需求
success, stories = client.get_my_stories("assignedTo")
# 类型: assignedTo(指派给我), openedBy(我创建的), reviewedBy(我评审的)
# 编辑需求
success, result = client.edit_story(story_id, title="新标题", pri="2")
# 关闭需求
success, result = client.close_story(story_id)
# ========== 产品管理 ==========
# 创建产品
success, result = client.create_product(
name="新产品",
code="NEW",
po="admin", # 产品负责人
status="normal"
)
# 查询产品列表
success, products = client.get_products()
# 创建发布计划
success, result = client.create_plan(
product_id="1",
title="V1.0版本",
begin="2026-03-01",
end="2026-03-31"
)
# 查询发布计划
success, plans = client.get_plans(product_id)
python
# ========== 项目管理 ==========
# 创建项目
success, result = client.create_project(
name="V1.0开发项目",
begin="2026-04-01",
end="2026-04-30",
code="V1",
days="22",
products=["1"], # 关联产品ID列表
plans=["1"], # 关联计划ID列表
desc="项目描述"
)
# 查询项目详情
success, project = client.get_project("1")
print(f"项目: {project['name']}, 状态: {project['status']}")
# 启动项目 (wait → doing)
success, result = client.start_project("1")
# 关闭项目
success, result = client.close_project("1")
# ========== 项目查询 ==========
# 查询项目列表
projects = client.get_project_list_old("all") # 状态: all, doing, done, suspended
# 查询项目任务
tasks = client.get_project_tasks_old(project_id, "all") # 状态: all, wait, doing, done, pause, cancel
# ========== 任务分解 ==========
# 创建任务
success, result = client.create_task(
project_id="1", # 项目ID
name="用户登录功能开发",
type="devel", # 任务类型: devel, test, design, study, discuss, ui, affair, misc
assignedTo="dev1",
pri="3", # 优先级: 0-4
estimate="8", # 预计工时
desc="实现用户登录功能"
)
# 批量创建任务
success, result = client.create_tasks(
project_id="1",
tasks=[
{"name": "前端开发", "type": "devel", "assignedTo": "dev1", "estimate": "8", "pri": "3"},
{"name": "后端开发", "type": "devel", "assignedTo": "dev2", "estimate": "16", "pri": "3"},
{"name": "接口联调", "type": "devel", "assignedTo": "dev1", "estimate": "4", "pri": "3"}
]
)
# 创建子任务
success, result = client.create_subtasks(
execution_id="1", # 项目/执行ID
parent_id="100", # 父任务ID
tasks=[
{"name": "前端开发", "estimate": "8", "assignedTo": "dev1", "type": "devel", "pri": "3"},
{"name": "后端开发", "estimate": "16", "assignedTo": "dev2", "type": "devel", "pri": "3"},
{"name": "接口联调", "estimate": "4", "assignedTo": "dev1", "type": "devel", "pri": "3"}
]
)
# ========== 任务指派 ==========
# 指派任务
success, result = client.assign_task(task_id, "zhangsan", "请处理")
# ========== 任务管理 ==========
# 取消任务
success, result = client.cancel_task(task_id)
# 删除任务
success, result = client.delete_task(task_id)
python
# ========== 日常查询 ==========
# 查看我的任务
success, tasks = client.get_my_tasks("assignedTo")
# 类型: assignedTo(指派给我), openedBy(我创建的), finishedBy(我完成的)
# 查看任务详情
success, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}") # wait, doing, pause, done, cancel, closed
print(f"预计: {task['estimate']}h") # 预计工时
print(f"消耗: {task['consumed']}h") # 已消耗工时
print(f"剩余: {task['left']}h") # 剩余工时
# ========== 任务流转 ==========
# 开始任务 (wait → doing)
success, result = client.start_task(task_id, "开始开发")
# 记录工时
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
success, result = client.record_estimate(task_id, [
{
"date": today,
"consumed": "3", # 本次消耗
"left": "5", # 剩余
"work": "完成了登录功能开发"
}
])
# 暂停任务 (doing → pause)
success, result = client.pause_task(task_id, "等待依赖接口")
# 继续任务 (pause → doing)
success, result = client.restart_task(task_id, "依赖已就绪")
# 完成任务 (doing → done) - 重要:先记录工时left=0,再完成
client.record_estimate(task_id, [
{"date": today, "consumed": "5", "left": "0", "work": "全部完成"}
])
success, result = client.finish_task(task_id, "开发完成")
# 关闭任务 (done → closed)
success, result = client.close_task(task_id, "已验收")
# 激活任务 (done/closed → doing)
success, result = client.activate_task(task_id, "重新开始")
# ========== Bug处理 ==========
# 查看我的Bug
success, bugs = client.get_my_bugs("assignedTo")
# 类型: assignedTo(指派给我), openedBy(我创建的), resolvedBy(我解决的)
# 查看Bug详情
success, bug = client.get_bug(bug_id)
# 解决Bug
success, result = client.resolve_bug(
bug_id=bug_id,
resolution="fixed", # fixed, postponed, willnotfix, duplicate, tostory
resolved_build="trunk",
comment="已修复登录校验问题"
)
python
# ========== Bug管理 ==========
# 创建Bug
success, result = client.create_bug(
product_id="1",
title="登录页面报错:500错误",
severity="3", # 严重程度: 1-4 (1最严重)
pri="3", # 优先级: 0-4
type="codeerror", # 类型: codeerror, config, install, security, etc.
steps="1.打开登录页\n2.输入账号密码\n3.点击登录\n4.出现500错误",
assignedTo="dev1",
project_id="1"
)
# 确认Bug
success, result = client.confirm_bug(bug_id, "确认是有效Bug")
# 指派Bug
success, result = client.assign_bug(bug_id, "dev1", "请处理")
# 关闭Bug (resolved → closed)
success, result = client.close_bug(bug_id, "验证通过")
# 激活Bug (closed → active)
success, result = client.activate_bug(bug_id, "问题重现")
# ========== 测试用例 ==========
# 创建测试用例
success, result = client.create_testcase(
product_id="1",
title="登录功能测试",
case_type="feature", # feature, performance, config, install, security, etc.
steps="1.打开登录页\n2.输入账号密码\n3.点击登录",
expect="登录成功"
)
# 查询测试用例
success, cases = client.get_testcases(product_id, "all")
# ========== 测试任务 ==========
# 创建测试任务
success, result = client.create_testtask(
product_id="1",
name="Sprint1测试",
begin="2026-03-20",
end="2026-03-25"
)
# 开始测试任务
success, result = client.start_testtask(task_id)
# 关闭测试任务
success, result = client.close_testtask(task_id)
text
┌─────────────┐
│ wait │ 待开始
└──────┬──────┘
│ start_task()
▼
┌─────────────┐
┌───────│ doing │ 进行中◀───────┐
│ └──────┬──────┘ │
│ │ │
pause_task() finish_task() activate_task()
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ done │ 已完成 │
│ └──────┬──────┘ │
│ │ │
│ close_task() restart_task()
│ │ │
│ ▼ │
┌──────┴──────┐ ┌─────────────┐ │
│ pause │ │ closed │ 已关闭 │
│ 暂停 │ └─────────────┘ │
└──────┬──────┘ │
│ │
└─────────────────────────────────────┘
restart_task()
cancel_task() ──────▶ cancel (已取消)
API调用顺序:
当前状态目标状态API说明waitdoingstart_task(task_id)开始任务doingpausepause_task(task_id)暂停任务pausedoingrestart_task(task_id)继续任务doingdonefinish_task(task_id)完成任务(建议先记录工时left=0)doneclosedclose_task(task_id)关闭任务done/closeddoingactivate_task(task_id)激活任务anycancelcancel_task(task_id)取消任务
text
┌─────────────┐
│ active │ 激活
└──────┬──────┘
│ resolve_bug()
▼
┌─────────────┐
│ resolved │ 已解决
└──────┬──────┘
│ close_bug()
▼
┌─────────────┐
│ closed │ 已关闭
└──────┬──────┘
│ activate_bug()
└──────────────┐
▼
┌─────────────┐
│ active │ 激活
└─────────────┘
API调用顺序:
当前状态目标状态API说明activeresolvedresolve_bug(bug_id, resolution)解决Bugresolvedclosedclose_bug(bug_id)关闭Bugclosedactiveactivate_bug(bug_id)激活Bug
python
# ✅ 正确:一次提交多条记录
client.record_estimate(task_id, [
{"date": "2026-03-27", "consumed": "2", "left": "6", "work": "开发"},
{"date": "2026-03-28", "consumed": "3", "left": "3", "work": "测试"}
])
# ❌ 错误:多次调用会覆盖之前记录
client.record_estimate(task_id, [{"date": "2026-03-27", "consumed": "2", ...}])
client.record_estimate(task_id, [{"date": "2026-03-28", "consumed": "3", ...}]) # 会覆盖!
python
# ✅ 正确流程
client.record_estimate(task_id, [
{"date": "2026-03-27", "consumed": "8", "left": "0", "work": "完成"}
])
client.finish_task(task_id, "开发完成")
# ❌ 错误:直接完成任务,没有记录最终工时
client.finish_task(task_id)
python
# 很多API返回HTML而非JSON,解析会失败,但操作实际成功
success, result = client.start_task(task_id)
# 建议:用get_task_detail验证
ok, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}") # 应为 'doing'
python
# ✅ 正确:使用resolve_bug
client.resolve_bug(bug_id, "fixed", "trunk", "已修复")
# ❌ 错误:不要用edit_bug修改状态,会丢失其他字段
# client.edit_bug(bug_id, status="resolved") # 会丢失产品、项目关联!
python
# 子任务数组参数,第一个任务用实际值,后续用ditto继承
client.create_subtasks(execution_id, parent_id, [
{"name": "前端", "estimate": "8", "assignedTo": "dev1", "type": "devel", "pri": "3"},
{"name": "后端", "estimate": "16", "assignedTo": "dev2", "type": "devel", "pri": "3"}
# 第二个任务会继承第一个任务的type和pri(API内部处理)
])
python
# get_my_tasks和get_my_bugs返回的是列表,不是字典
success, tasks = client.get_my_tasks("assignedTo")
if success:
for task in tasks: # tasks是列表
print(f"[{task['id']}] {task['name']} ({task['status']})")
python
# 查看我的任务
success, tasks = client.get_my_tasks("assignedTo")
# 统计状态
stats = {"wait": 0, "doing": 0, "pause": 0, "done": 0}
for task in tasks:
status = task.get("status", "unknown")
if status in stats:
stats[status] += 1
print(f"我的任务: 待开始{stats['wait']}, 进行中{stats['doing']}, 暂停{stats['pause']}, 已完成{stats['done']}")
python
# 1. 查看任务详情
success, task = client.get_task_detail(task_id)
print(f"任务: {task['name']}, 预计工时: {task['estimate']}h")
# 2. 开始任务
success, result = client.start_task(task_id, "开始开发")
# 3. 验证
ok, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}") # doing
python
from datetime import datetime
# 记录今天的工时
today = datetime.now().strftime("%Y-%m-%d")
success, result = client.record_estimate(task_id, [
{
"date": today,
"consumed": "3", # 今天消耗3小时
"left": "5", # 剩余5小时
"work": "完成了用户登录功能开发"
}
])
# 验证
ok, task = client.get_task_detail(task_id)
print(f"总消耗: {task['consumed']}h, 剩余: {task['left']}h")
python
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
# 1. 记录最终工时
client.record_estimate(task_id, [
{"date": today, "consumed": "5", "left": "0", "work": "全部完成"}
])
# 2. 完成任务
success, result = client.finish_task(task_id, "开发完成,已自测")
# 3. 验证
ok, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}") # done
print(f"完成人: {task['finishedBy']}") # admin
python
# 创建Bug
success, result = client.create_bug(
product_id="1",
title="登录页面500错误",
severity="2", # 严重
pri="3",
type="codeerror",
steps="1.打开登录页\n2.输入admin/admin\n3.点击登录\n4.出现500错误",
assignedTo="dev1",
comment="优先处理"
)
# 查看我的Bug
success, bugs = client.get_my_bugs("openedBy")
for bug in bugs:
print(f"[{bug['id']}] {bug['title']} ({bug['status']})")
python
# 1. 查看Bug详情
success, bug = client.get_bug(bug_id)
print(f"标题: {bug['title']}, 状态: {bug['status']}")
# 2. 解决Bug
success, result = client.resolve_bug(
bug_id=bug_id,
resolution="fixed",
resolved_build="trunk",
comment="已修复登录校验逻辑"
)
# 3. 关闭Bug
success, result = client.close_bug(bug_id, "验证通过,问题已修复")
# 4. 验证
ok, bug = client.get_bug(bug_id)
print(f"状态: {bug['status']}") # closed
print(f"关闭人: {bug['closedBy']}")
python
# 查询父任务
tasks = client.get_project_tasks_old(project_id, "all")
parent_task_id = list(tasks.keys())[0]
# 创建子任务
success, result = client.create_subtasks(
execution_id=project_id,
parent_id=parent_task_id,
tasks=[
{"name": "前端开发", "estimate": "8", "assignedTo": "dev1"},
{"name": "后端开发", "estimate": "16", "assignedTo": "dev2"},
{"name": "接口联调", "estimate": "4", "assignedTo": "dev1"}
]
)
python
# 批量创建需求
requirements = ["用户登录", "商品浏览", "购物车", "订单管理"]
for req in requirements:
client.create_story(product_id, req, pri="3", estimate="8")
# 批量记录工时
from datetime import datetime, timedelta
today = datetime.now()
records = []
for i in range(5):
records.append({
"date": (today - timedelta(days=i)).strftime("%Y-%m-%d"),
"consumed": "2",
"left": str(10 - i * 2),
"work": f"开发进度{i*20}%"
})
client.record_estimate(task_id, records)
python
# 项目任务状态统计
tasks = client.get_project_tasks_old(project_id, "all")
stats = {}
for tid, task in tasks.items():
status = task.get("status", "unknown")
stats[status] = stats.get(status, 0) + 1
print(f"任务统计: {stats}")
# 输出: {'wait': 5, 'doing': 3, 'done': 10, 'pause': 1, 'cancel': 2}
python
import json
# 导出我的任务
success, tasks = client.get_my_tasks("assignedTo")
with open("my_tasks.json", "w", encoding="utf-8") as f:
json.dump(tasks, f, ensure_ascii=False, indent=2)
# 导出我的Bug
success, bugs = client.get_my_bugs("assignedTo")
with open("my_bugs.json", "w", encoding="utf-8") as f:
json.dump(bugs, f, ensure_ascii=False, indent=2)
API说明参数create_product(name, code, ...)创建产品name, code, type, po, qd, rd, status, descget_products()查询产品列表-get_product(product_id)查询产品详情product_idedit_product(product_id, ...)编辑产品product_id, **kwargsclose_product(product_id)关闭产品product_iddelete_product(product_id)删除产品product_id
API说明参数create_story(product_id, title, ...)创建需求product_id, title, pri, estimate, spec, ...get_story(story_id)查询需求详情story_idget_my_stories(story_type)查询我的需求story_type: assignedTo, openedBy, reviewedBy, closedByedit_story(story_id, ...)编辑需求story_id, **kwargsclose_story(story_id)关闭需求story_idactivate_story(story_id)激活需求story_iddelete_story(story_id)删除需求story_id
API说明参数create_plan(product_id, title, ...)创建计划product_id, title, begin, end, descget_plans(product_id)查询计划列表product_iddelete_plan(plan_id)删除计划plan_id
API说明参数create_project(name, begin, end, ...)创建项目name, begin, end, code, days, products, plans, descget_project(project_id)查询项目详情project_idstart_project(project_id)启动项目project_idclose_project(project_id)关闭项目project_idget_project_list_old(status)查询项目列表status: all, doing, done, suspendedget_project_tasks_old(project_id, status)查询项目任务project_id, statusget_project_bugs(project_id, status)查询项目Bugproject_id, status
API说明参数create_task(project, name, type, ...)创建任务project, name, type, story, module, assignedTo, pri, estimate, desccreate_tasks(project, tasks)批量创建任务project, tasks列表get_my_tasks(task_type)查询我的任务task_type: assignedTo, openedBy, finishedBy, closedBy, canceledByget_task_detail(task_id)查询任务详情task_idcreate_subtasks(execution_id, parent_id, tasks)创建子任务execution_id, parent_id, tasks列表start_task(task_id, comment)开始任务task_id, commentpause_task(task_id, comment)暂停任务task_id, commentrestart_task(task_id, comment)继续任务task_id, commentfinish_task(task_id, comment)完成任务task_id, commentclose_task(task_id, comment)关闭任务task_id, commentactivate_task(task_id, comment)激活任务task_id, commentcancel_task(task_id)取消任务task_iddelete_task(task_id)删除任务task_idassign_task(task_id, assigned_to, comment)指派任务task_id, assigned_to, commentrecord_estimate(task_id, records)记录工时task_id, records列表
API说明参数get_my_bugs(bug_type)查询我的Bugbug_type: assignedTo, openedBy, resolvedBy, closedByget_bug(bug_id)查询Bug详情bug_idcreate_bug(product_id, title, ...)创建Bugproduct_id, title, severity, pri, type, steps, assignedTo, ...resolve_bug(bug_id, resolution, ...)解决Bugbug_id, resolution, resolved_build, commentclose_bug(bug_id, comment)关闭Bugbug_id, commentactivate_bug(bug_id, comment)激活Bugbug_id, commentassign_bug(bug_id, assigned_to, comment)指派Bugbug_id, assigned_to, commentconfirm_bug(bug_id, comment)确认Bugbug_id, commentdelete_bug(bug_id)删除Bugbug_id
API说明参数get_testcases(product_id, browse_type)查询测试用例product_id, browse_typeget_testcase(case_id)查询用例详情case_idcreate_testcase(product_id, title, ...)创建测试用例product_id, title, case_type, steps, expect, ...delete_testcase(case_id)删除测试用例case_idget_testsuites(product_id)查询测试套件product_idcreate_testsuite(product_id, name, desc)创建测试套件product_id, name, descget_testtasks(product_id, task_type)查询测试任务product_id, task_typecreate_testtask(product_id, name, ...)创建测试任务product_id, name, begin, end, descstart_testtask(task_id)开始测试任务task_idclose_testtask(task_id)关闭测试任务task_id
Q: 认证失败怎么办?
python
# 检查凭证
credentials = read_credentials()
print(credentials) # 确保endpoint, username, password正确
# 手动获取session
sid = client.get_session()
if not sid:
print("认证失败,请检查用户名密码")
Q: API返回success=False但操作成功?
python
# 很多API返回HTML而非JSON,解析会失败
# 建议:用查询接口验证操作结果
success, result = client.start_task(task_id)
# 返回False但实际成功
ok, task = client.get_task_detail(task_id)
print(task['status']) # 验证状态是否变为doing
Q: 工时记录不生效?
python
# 确保参数格式正确
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d") # 必须是YYYY-MM-DD格式
success, result = client.record_estimate(task_id, [
{
"date": today,
"consumed": "2", # 字符串格式
"left": "6", # 字符串格式
"work": "开发中"
}
])
# 验证
ok, task = client.get_task_detail(task_id)
print(f"消耗: {task['consumed']}, 剩余: {task['left']}")
Q: 创建子任务失败?
python
# 确保参数完整
tasks = [
{
"name": "前端开发", # 必需
"estimate": "8", # 必需
"assignedTo": "admin", # 必需
"type": "devel", # 可选,默认devel
"pri": "3" # 可选,默认3
}
]
success, result = client.create_subtasks(
execution_id="1", # 项目/执行ID
parent_id="100", # 父任务ID
tasks=tasks
)
lib/zentao_client.pydocs/测试报告-工单客服系统.mdMIT License - 自由使用、修改和分发