用 python-tdd-with-uv:讓 AI Agent 按紅-綠-重構寫 Python

前言

讓 AI 幫忙寫 Python 時,常見問題不是「寫不出來」,而是「一次寫太多」。Agent 容易先堆實現、再補測試,或者一口氣寫一串尚未失敗的用例,結果接口提前定死、測試只貼實現細節,後面改起來很痛。

TDD(測試驅動開發)本來就是用來約束這種衝動的:先寫一個失敗的測試,再寫剛好夠通過的代碼,再重構。Astral 出品的 uv 又把依賴安裝、虛擬環境和命令執行收成一套很快的工具鏈。把這兩件事寫進一份可複用的 SKILL.md,就是 python-tdd-with-uv 要做的事——讓 Cursor、Claude Code、Codex CLI 等支持 Agent Skills 的工具,在寫 Python 時默認走「小步、先測、用 uv 跑」的流程。

這是什麼

python-tdd-with-uv 是一份 Agent Skill,收錄在 spencerpauly 維護的 awesome-cursor-skills 倉庫中,路徑爲 resources/python-tdd-with-uv/。官方一句話定位是:用 uv 做包管理,在 Python 裏做測試驅動開發,覆蓋紅-綠-重構循環、垂直切片,以及用 uv 初始化項目。

Skill 本體是標準的 SKILL.md(YAML frontmatter + 正文指令)。frontmatter 裏 namepython-tdd-with-uvdescription 說明適用場景,並聲明 user-invocable: true,因此除了 Agent 按描述自動選用外,也可以在對話裏用 /python-tdd-with-uv 顯式調用(具體以所用工具對 Skills 的支持爲準)。

它解決的問題很具體:把「怎麼立項、怎麼加 pytest、怎麼一輪只推進一個行爲、怎麼用 uv run 跑測試」寫成 Agent 必須遵守的規則,而不是每次口頭提醒。

核心能力

根據倉庫中的 SKILL.md 原文,該 Skill 主要約束以下幾件事。

  1. 用 uv 搭項目與測試依賴
    檢查 uv 是否可用;沒有 pyproject.toml 時用 uv init;用 uv add --dev pytest pytest-cov 加入開發依賴;用 uv run pytest --co 確認測試發現正常。

  2. 垂直切片式的紅-綠-重構
    同一時間只允許一個失敗測試:RED 寫一個失敗用例 → GREEN 寫最少實現讓它通過 → REFACTOR 在行爲不變的前提下整理代碼 → 再重複。禁止「先實現再補測」,也禁止一次寫多個失敗測試。

  3. 寫代碼前先做簡短規劃
    先回答:要改哪些接口(函數、類、API)?哪些行爲最關鍵?能否做成可測設計(依賴注入、少用全局狀態)?

  4. 測試寫法與邊界
    測試斷言可觀察行爲,而不是實現細節;Mock 只用在系統邊界(I/O、網絡、時鐘等)。推薦按 tests/test_<module>.py 用類分組相關行爲。

  5. 統一用 uv run 執行
    所有命令走 uv run,不要手動 activate 虛擬環境;同時提交 pyproject.tomluv.lock

Skill 文末還指向了幾份相關資料作延伸閱讀:mattpocock 的垂直切片 TDD Skill、nizos/tdd-guard(用 hooks 強制 TDD)、以及 s2005/uv-skill(uv 工作流模式)。這些是參考鏈接,不是本 Skill 的內置腳本。

關於 uv 本身:它是 Astral(Ruff 同門)用 Rust 寫的 Python 包與項目管理工具,官方文檔稱可替代 pip、pip-tools、poetry、virtualenv 等常見工具鏈的一部分,並提供跨平臺的 uv.lock。本 Skill 並不重新發明 uv,只是把「TDD 節奏 + uv 命令約定」綁在一起,方便 Agent 執行。

安裝與啓用

手動放入項目(各工具通用)

Skill 的實質就是一個目錄裏的 SKILL.md。從官方倉庫取出後,按工具約定放到對應目錄即可。awesome-cursor-skills 的 README 說明:在 Cursor 中可複製到項目的 .cursor/skills/(或個人目錄)下,由 Agent 自動發現。

# 示例:只拉取該 Skill 到當前項目(Cursor 項目級)
mkdir -p .cursor/skills/python-tdd-with-uv
curl -fsSL \
  https://raw.githubusercontent.com/spencerpauly/awesome-cursor-skills/main/resources/python-tdd-with-uv/SKILL.md \
  -o .cursor/skills/python-tdd-with-uv/SKILL.md

也可整倉克隆後,把 resources/python-tdd-with-uv/ 拷到本地 skills 目錄。

Cursor 文檔,Skills 會從下列位置加載(項目級 / 用戶級):

位置 範圍
.cursor/skills/.agents/skills/ 當前項目
~/.cursor/skills/~/.agents/skills/ 用戶全局
.claude/skills/.codex/skills/ 及對應家目錄路徑 兼容 Claude Code / Codex

每個 Skill 應是「文件夾 + SKILL.md」,文件夾名與 frontmatter 裏的 name 一致(此處爲 python-tdd-with-uv)。

用 skills CLI 安裝(Claude Code 等)

第三方目錄 Claude Skills Hub 給出的安裝示例爲:

npx skills add spencerpauly/awesome-cursor-skills --skill python-tdd-with-uv --agent claude-code

該命令會把 Skill 裝進當前項目的 .claude/skills/。若你使用 Codex 等其它 agent 標識,以 npx skills 當時支持的參數爲準。

系統側依賴:先裝好 uv

本 Skill 假設本機已有 uv。可按 uv 官方安裝說明 安裝,例如 macOS / Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh
uv --version

裝好 Skill 之後,在 Agent 對話裏直接說「按 TDD 用 uv 實現某某功能」,或輸入 /python-tdd-with-uv,Agent 應讀取該 Skill 並按其中步驟執行。

典型用法

下面流程均來自官方 SKILL.md,可直接復現。

1. 初始化項目與 pytest

uv --version

# 若還沒有 pyproject.toml
uv init

uv add --dev pytest pytest-cov
uv run pytest --co

--co(collect-only)只收集用例、不執行,用來確認測試發現配置是否正常。

2. 按垂直切片推進一個行爲

規劃階段先想清楚接口與關鍵路徑,然後嚴格一輪只做一個失敗測試。Skill 給出的循環是:

RED   → 爲下一個行爲寫「一個」失敗測試
GREEN → 寫最少代碼讓它通過
REFACTOR → 清理結構,不改變行爲
REPEAT

硬性規則包括:沒有失敗測試就不要寫實現;每次改完都跑 uv run pytest;斷言行爲而非內部細節;Mock 僅用於 I/O、網絡、時鐘等邊界。

3. 推薦的測試文件結構

# tests/test_<module>.py

class TestFeatureName:
    """Group related behaviors."""

    def test_does_expected_thing_when_given_input(self):
        result = function_under_test(input_value)
        assert result == expected

    def test_raises_when_given_invalid_input(self):
        with pytest.raises(ValueError):
            function_under_test(bad_input)

4. 常用測試命令

uv run pytest                      # 全部測試
uv run pytest tests/test_foo.py    # 單文件
uv run pytest -k "test_name"       # 按名稱過濾
uv run pytest --cov=src            # 帶覆蓋率
uv run pytest -x                   # 遇失敗即停

5. uv 日常命令速查

uv add <package>           # 添加依賴
uv add --dev <package>     # 添加開發依賴
uv remove <package>        # 移除依賴
uv sync                    # 按鎖文件同步環境
uv run <command>           # 在託管環境中執行
uv lock                    # 重新生成鎖文件

Skill 明確要求:始終用 uv run 執行命令,不要手動激活 venv;pyproject.tomluv.lock 一併提交,保證環境可復現。

適用場景與注意事項

比較合適的情況:

  • 用 AI Agent 從零搭 Python 小項目,希望默認走 pytest + TDD。
  • 給已有倉庫補行爲時,希望 Agent「一次只喫透一個切片」,避免大段投機實現。
  • 團隊已經或準備統一用 uv 管理依賴與鎖文件。

需要注意的限制:

  • 這是「流程指令」Skill,不是替你寫好業務代碼的框架;效果取決於 Agent 是否認真遵循 SKILL.md。
  • 本機必須先安裝 uv;Skill 不會代替系統包管理器去裝 uv。
  • 「一次只允許一個失敗測試」會故意變慢一點——這是爲了防止過度設計;若你明確只要快速草稿、不要 TDD,就不必啓用該 Skill。
  • Mock 規則偏嚴:內部協作對象不該輕易 mock;若項目大量依賴複雜外部服務,需要先想好邊界怎麼切。
  • Skill 正文引用了 mattpocock/skills、tdd-guard、uv-skill 等延伸方案,但它們是獨立項目,默認安裝本 Skill 時並不會一併裝上。

小結

python-tdd-with-uv 把兩件近年 Python / AI 編程裏很實用的約定綁在一起:一是紅-綠-重構與垂直切片,二是用 uv 管依賴並用 uv run pytest 閉環驗證。它來自 awesome-cursor-skills 的 Testing 分類,源文件在:

https://github.com/spencerpauly/awesome-cursor-skills/tree/main/resources/python-tdd-with-uv

SKILL.md 放進項目的 skills 目錄(或按 CLI 裝到 .claude/skills/),再讓 Agent 做 Python 功能開發時,就能少寫一點「請先寫測試」的口頭約束,多一點可復現的小步節奏。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜