Files
cmpdd/tests/test_paths.py
T
chengmaandClaude Opus 4.8 b1e38ffd7a feat(T-003): 建立日志与运行产物目录策略
- src/paths.py: 集中管理 logs/、artifacts/ 路径与产物命名
  (artifacts/<task_id>/<时间戳>_<step>.png|.xml),_safe 安全化防路径穿越,
  运行时自动创建且被 .gitignore 忽略。
- src/logging_config.py: 统一日志格式(含 task_id/step),控制台 + logs/app.log,
  缺上下文时由 filter 补默认值,setup 幂等;约定不记录敏感信息。
- src/main.py: 启动时初始化运行目录与日志。
- 运行方式统一为 python -m src.main(绝对导入下的唯一干净入口),
  同步替换 00/03/05/current-state 文档命令与 dev.bat。
- 文档:04 §七 补 paths.py 与产物命名规则;tasks/progress/current-state 更新。

验证:compileall OK;unittest Ran 17 tests OK;python -m src.main exit=0,logs/app.log 写入正常。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 17:32:28 +08:00

42 lines
1.6 KiB
Python

"""运行产物路径策略测试(T-003)。"""
import tempfile
import unittest
from pathlib import Path
from unittest import mock
from src import paths
class PathsTest(unittest.TestCase):
def test_safe_replaces_illegal_chars(self):
self.assertEqual(paths._safe("color/size..x"), "color_size__x")
self.assertEqual(paths._safe("ok-_1"), "ok-_1")
def test_safe_empty_fallback(self):
self.assertEqual(paths._safe(""), "unknown")
self.assertEqual(paths._safe("/.."), "___")
def test_screenshot_and_xml_paths(self):
with tempfile.TemporaryDirectory() as tmp:
with mock.patch.object(paths, "ARTIFACTS_DIR", Path(tmp)):
png = paths.screenshot_path("T1", "open_product")
xml = paths.ui_xml_path("T1", "open_product")
self.assertTrue(png.name.endswith(".png"))
self.assertTrue(xml.name.endswith(".xml"))
# 同一任务归到 artifacts/<task_id>/ 子目录
self.assertEqual(png.parent.name, "T1")
self.assertEqual(xml.parent.name, "T1")
# 目录已被创建
self.assertTrue(png.parent.is_dir())
def test_illegal_task_id_cannot_escape_root(self):
"""task_id 含路径穿越字符时被安全化隔离,不逃逸 artifacts 根。"""
with tempfile.TemporaryDirectory() as tmp:
with mock.patch.object(paths, "ARTIFACTS_DIR", Path(tmp)):
p = paths.screenshot_path("../evil", "step")
self.assertTrue(str(p.resolve()).startswith(str(Path(tmp).resolve())))
if __name__ == "__main__":
unittest.main()