auto-sync: 2026-06-05 14:09:49
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
"""#11 Bootstrap 四段式拼装单元测试(v2.1)
|
||||
|
||||
覆盖:
|
||||
- T1: build(task, role) 4 段结构
|
||||
- T1: build(role, task_context) 4 段结构
|
||||
- T2: token 估算 + 预算告警
|
||||
- T3: 缺失组件降级
|
||||
- T4: build_for_task 便捷方法
|
||||
- T5: _read_skill fallback
|
||||
- T6: ROLE_SKILL_MAP 覆盖
|
||||
- T5: _read_skill fallback (skipped — removed in API refactor)
|
||||
- T6: ROLE_SKILL_MAP 覆盖 (skipped — removed in API refactor)
|
||||
"""
|
||||
|
||||
import pytest
|
||||
@@ -24,57 +24,52 @@ def builder():
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# T1: build(task, role) 4 段结构
|
||||
# T1: build(role, task_context) 4 段结构
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestFourSectionBuild:
|
||||
def test_basic_executor_build(self, builder):
|
||||
b = builder.build(
|
||||
task={"task_id": "t1", "title": "Write tests", "description": "Write unit tests",
|
||||
"must_haves": "100% coverage", "status": "claimed"},
|
||||
role="executor",
|
||||
task_context={"task_id": "t1", "title": "Write tests", "description": "Write unit tests",
|
||||
"must_haves": "100% coverage", "status": "claimed"},
|
||||
)
|
||||
# 段 1: 任务上下文
|
||||
# 段: 任务上下文
|
||||
assert "Write tests" in b
|
||||
assert "t1" in b
|
||||
assert "100% coverage" in b
|
||||
# 段 4: 硬约束
|
||||
assert "review" in b
|
||||
assert "handoff" in b
|
||||
|
||||
def test_basic_reviewer_build(self, builder):
|
||||
b = builder.build(
|
||||
task={"task_id": "t2", "title": "Review PR"},
|
||||
role="reviewer",
|
||||
task_context={"task_id": "t2", "title": "Review PR"},
|
||||
)
|
||||
assert "Review PR" in b
|
||||
# 段 4: reviewer 硬约束
|
||||
assert "pass/fail" in b or "pass" in b
|
||||
|
||||
def test_planner_build(self, builder):
|
||||
b = builder.build(
|
||||
task={"task_id": "t3", "title": "Plan sprint"},
|
||||
role="planner",
|
||||
task_context={"task_id": "t3", "title": "Plan sprint"},
|
||||
)
|
||||
assert "Plan sprint" in b
|
||||
|
||||
def test_depends_on_outputs_injected(self, builder):
|
||||
b = builder.build(
|
||||
task={
|
||||
role="executor",
|
||||
task_context={
|
||||
"title": "T",
|
||||
"depends_on_outputs": [
|
||||
{"task_id": "t0", "summary": "Data downloaded"},
|
||||
],
|
||||
},
|
||||
role="executor",
|
||||
)
|
||||
assert "前序产出" in b
|
||||
assert "Data downloaded" in b
|
||||
|
||||
def test_no_depends_on_omitted(self, builder):
|
||||
b = builder.build(
|
||||
task={"title": "T"},
|
||||
role="executor",
|
||||
task_context={"title": "T"},
|
||||
)
|
||||
assert "前序产出" not in b
|
||||
|
||||
@@ -99,12 +94,12 @@ class TestTokenEstimation:
|
||||
|
||||
class TestGracefulDegradation:
|
||||
def test_empty_task(self, builder):
|
||||
b = builder.build(task={}, role="executor")
|
||||
b = builder.build(role="executor", task_context={})
|
||||
assert b # 不为空
|
||||
assert "硬约束" in b
|
||||
assert "# Role: executor" in b
|
||||
|
||||
def test_partial_task(self, builder):
|
||||
b = builder.build(task={"title": "Only title"}, role="executor")
|
||||
b = builder.build(role="executor", task_context={"title": "Only title"})
|
||||
assert "Only title" in b
|
||||
|
||||
|
||||
@@ -120,36 +115,37 @@ class TestBuildForTask:
|
||||
title = "Build Feature"
|
||||
description = "Implement X with tests"
|
||||
must_haves = "Unit tests, Documentation"
|
||||
status = "claimed"
|
||||
task_type = "coding"
|
||||
risk_level = "low"
|
||||
task = MockTask()
|
||||
b = builder.build_for_task(task, role="executor")
|
||||
assert "Build Feature" in b
|
||||
assert "Implement X" in b
|
||||
|
||||
def test_build_for_task_ignores_kwargs(self, builder):
|
||||
"""build_for_task 忽略旧参数"""
|
||||
"""build_for_task accepts project_config and experiences"""
|
||||
class MockTask:
|
||||
id = "t1"
|
||||
title = "T"
|
||||
description = ""
|
||||
must_haves = ""
|
||||
status = ""
|
||||
task_type = "coding"
|
||||
risk_level = "low"
|
||||
task = MockTask()
|
||||
# 旧参数 project_config/experiences 不应报错
|
||||
# project_config/experiences are valid kwargs for build_for_task
|
||||
b = builder.build_for_task(
|
||||
task, role="executor",
|
||||
project_config={"name": "Old"},
|
||||
experiences=[{"x": 1}],
|
||||
)
|
||||
assert "T" in b
|
||||
# 不应出现旧参数内容
|
||||
assert "Old" not in b
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# T5: _read_skill fallback
|
||||
# T5: _read_skill fallback (removed in API refactor)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.mark.skip(reason="_read_skill removed in API refactor")
|
||||
class TestReadSkillFallback:
|
||||
def test_missing_skill_file_returns_empty(self, builder):
|
||||
"""Skill 文件不存在时返回空字符串,不抛异常"""
|
||||
@@ -158,15 +154,15 @@ class TestReadSkillFallback:
|
||||
|
||||
def test_existing_skill_file_read(self, builder):
|
||||
"""能读取实际存在的 Skill 文件"""
|
||||
# blackboard-executor 应该存在(P1 已创建)
|
||||
result = builder._read_skill("blackboard-executor")
|
||||
assert "执行" in result or "executor" in result.lower()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# T6: ROLE_SKILL_MAP 覆盖
|
||||
# T6: ROLE_SKILL_MAP 覆盖 (removed in API refactor)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.mark.skip(reason="ROLE_SKILL_MAP removed in API refactor")
|
||||
class TestRoleSkillMap:
|
||||
def test_all_roles_mapped(self):
|
||||
assert set(BootstrapBuilder.ROLE_SKILL_MAP.keys()) == {
|
||||
|
||||
Reference in New Issue
Block a user