Skip to content

Commit f9eda24

Browse files
luiseimanclaude
andcommitted
feat: python-fastapi testing rules from cotiza-api-cloud practices
- Add Patching, Concurrency Tests, and Migration print→logging sections to tests.md - Add 2 common errors to backend.md (replace_all uniqueness, local asyncio patching) - Add launch.json.tmpl template for uvicorn dev server - Clean processed inbox practices Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aa80948 commit f9eda24

4 files changed

Lines changed: 27 additions & 34 deletions

File tree

practices/inbox/2026-03-21-project-crm-session-changes.md

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"version": "0.0.1",
3+
"configurations": [
4+
{
5+
"name": "api",
6+
"runtimeExecutable": "python",
7+
"runtimeArgs": ["-u", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080", "--reload"],
8+
"port": 8080
9+
}
10+
]
11+
}

stacks/python-fastapi/rules/backend.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ Python 3.12+, FastAPI, async/await nativo. Type hints en funciones públicas. Ru
3030
- Olvidar `await` en async calls → retorna coroutine, no resultado
3131
- `response_model` sin `model_config = ConfigDict(from_attributes=True)` → falla con ORM
3232
- Background tasks que no capturan excepciones → mueren silenciosamente
33+
- `replace_all=True` in Edit without checking uniqueness — multiple similar patterns in a file get clobbered
34+
- Local `import asyncio` inside functions: `patch("module.asyncio.sleep")` fails with AttributeError — use `patch("asyncio.sleep")` directly

stacks/python-fastapi/rules/tests.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ globs: "tests/**/*.py"
1616
- Fixtures async: `@pytest_asyncio.fixture` (no `@pytest.fixture` para async)
1717
- httpx.AsyncClient para test de endpoints FastAPI
1818

19+
## Patching
20+
- Patch targets follow the namespace where the name is **used**, not where it's **defined**. After refactoring a method to a new module, update all `patch()` paths accordingly
21+
- If a module uses `import asyncio` locally inside a function (not at top-level), patch `asyncio.sleep` globally — not `module.asyncio.sleep`
22+
- After delegating/extracting methods to new modules, search all `patch()` calls targeting the old module's internals
23+
24+
## Concurrency Tests
25+
- Threads don't propagate exceptions to the main thread by default. Use a `_run_threads(target, n, *args)` helper that wraps target in try/except, collects exceptions in a shared list, and asserts empty after join
26+
- Verify RLock by behavior (acquire twice from same thread with `blocking=False`), not by `type().__name__` — internal type `_RLock` is private and may change
27+
28+
## Migration print→logging
29+
- Replace adjacent `print(f"... {e}")` + `traceback.print_exc()` with a single `logger.exception(f"... {e}")` — it includes the full traceback
30+
- Remove orphaned `import traceback` after migration
31+
- Remove module prefix constants (e.g. `PRINT_PREFIX = "[module]"`) — logger name provides this
32+
1933
## Coverage
2034
- No apuntar a 100% — cubrir paths críticos y edge cases
2135
- Priorizar: happy path, error handling, boundary conditions

0 commit comments

Comments
 (0)