Skip to main content

tdd

HelmLog-specific test patterns and the pre-existing-error allowlist for ruff/mypy. The Red-Green-Refactor cycle and lint commands are already mandated in CLAUDE.md — this skill encodes only the patterns and known-pre-existing-errors list that aren't recoverable from existing tests at a glance. TRIGGER when writing or modifying Python source code in src/helmlog/. DO NOT trigger for documentation, config, templates, CSS/JS, skill definitions, or changes that don't affect runtime behavior.

跳到安装

来源信息

仓库
weaties/helmlog
最近来源活动
2026年6月4日 19:29
检测到的 SKILL.md 语言
英语
星标
2
分支
2

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
2 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
tdd
description
HelmLog-specific test patterns and the pre-existing-error allowlist for ruff/mypy. The Red-Green-Refactor cycle and lint commands are already mandated in CLAUDE.md — this skill encodes only the patterns and known-pre-existing-errors list that aren't recoverable from existing tests at a glance. TRIGGER when writing or modifying Python source code in src/helmlog/. DO NOT trigger for documentation, config, templates, CSS/JS, skill definitions, or changes that don't affect runtime behavior.
# TDD — HelmLog patterns CLAUDE.md already mandates: failing test → implement → green → lint. This skill encodes only the project-specific bits that aren't obvious from existing tests: ## Test patterns **Storage tests** — use the shared `storage` fixture from `conftest.py` (in-memory SQLite, fully migrated; never construct `Storage` by hand in a test): ```python @pytest.mark.asyncio async def test_my_feature(storage: Storage) -> None: # storage is ready with all migrations applied ... ``` **Web route tests** — use `httpx.AsyncClient` with `ASGITransport`, not the sync `TestClient`: ```python @pytest.mark.asyncio async def test_my_endpoint(storage: Storage) -> None: from helmlog.web import create_app app = create_app(storage) async with httpx.AsyncClient( transport=ASGITransport(app=app), base_url="http://test" ) as client: resp = await client.get("/api/my-endpoint") assert resp.status_code == 200 ``` **Hardware mocking** — patch hardware modules at the import site so the test never touches real devices: ```python with patch("helmlog.cameras.httpx.AsyncClient") as mock_client: ... ``` Hardware modules to mock: `audio.py`, `can_reader.py`, `sk_reader.py`, `cameras.py`. ## Don't rationalize skipping the cycle The cycle only helps if you don't talk yourself out of it. Common excuses and their rebuttals: | Rationalization | Rebuttal | |---|---| | "This change is too small to need a test." | Size predicts neither breakage nor regression. A failing test first is what proves the change does what you think — write it. | | "I'll write the test after I see it work." | Test-after rationalizes whatever the code already does, bugs included. Red-Green-Refactor is mandated in CLAUDE.md for a reason. | | "It's just a renderer/route tweak — I'll eyeball it." | Web routes are the easiest place to ship a silent 500. Use the `AsyncClient`/`ASGITransport` pattern above. | | "Tests pass, so it's correct." | Passing tests are evidence, not proof. Confirm the test exercises the new behavior and would actually fail without your change. | | "ruff/mypy is noisy here, I'll skip the lint gate." | Only the pre-existing-error allowlist below is exempt. Everything else is green-before-PR. | ## Pre-existing errors to ignore Do not fix these unless explicitly asked — they are tracked separately: - `web.py`: `Item "None" of "datetime | None" has no attribute "isoformat"` - `web.py`: `Item "None" of "AudioRecorder | None" has no attribute "stop"` (×2) - `main.py`: `Unused "type: ignore" comment` - `storage.py`: 2 pre-existing E501 line-length violations
在 GitHub 查看