You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**Adding helpers at the top of the file.** It is tempting to place a new helper near the top, before any existing function. Always scroll down to find the caller first, then add the helper below it.
207
207
-**Placing a helper above the function that introduces it.** Even if a helper is only a few lines long, it should still follow its caller so the intent is clear before the detail.
208
+
209
+
## Caching IO-intensive private helpers
210
+
211
+
When a private helper function performs file I/O or another expensive operation and may be called more than once during a single high-level operation, decorate it with `@functools.cache` to avoid redundant work.
212
+
213
+
### When to apply
214
+
215
+
Apply `@functools.cache` to a private helper when all of the following are true:
216
+
217
+
- It performs file I/O, a subprocess call, or another expensive operation.
218
+
- It can be called more than once within a single invocation of its public caller(s).
219
+
- Its return value is deterministic with respect to the project state — the same inputs always produce the same result within a single process run.
220
+
221
+
Do **not** cache functions that write files, mutate state, or produce side effects.
222
+
223
+
### Procedure
224
+
225
+
1. Add `import functools` to the module if not already present.
226
+
2. Decorate the private helper with `@functools.cache`.
227
+
3. Register the function's cache-clear call in the `clear_functools_caches` autouse fixture in `tests/conftest.py` (see `usethis-python-test` for details).
228
+
229
+
### Common mistakes
230
+
231
+
-**Caching functions with side effects.**`@functools.cache` is only appropriate for pure, read-only operations. Functions that write files or change state should never be cached.
232
+
-**Forgetting to register cache clearing.** A cached function whose cache is never cleared between tests will cause test pollution — one test's cached value silently affects the next.
Copy file name to clipboardExpand all lines: .agents/skills/usethis-python-test/SKILL.md
+16-1Lines changed: 16 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ description: General guidelines for writing tests in the usethis project, includ
4
4
compatibility: usethis, Python, pytest
5
5
license: MIT
6
6
metadata:
7
-
version: "1.1"
7
+
version: "1.2"
8
8
---
9
9
10
10
# Python Test Guidelines
@@ -93,3 +93,18 @@ with change_cwd(tmp_path), files_manager():
93
93
94
94
-**FileManager-only operations** (e.g. `use_*` functions, `get_deps_from_group`, assertions on config state): safe to combine in one context.
95
95
-**Subprocess calls** (e.g. `call_uv_subprocess`, `subprocess.run`, `call_subprocess`): require an atomic write first, so exit the `files_manager` context before running them.
96
+
97
+
## Clearing functools caches between tests
98
+
99
+
When `@functools.cache` is added to a production function (see `usethis-python-code`), its cache must be cleared between tests to prevent one test's cached result from polluting subsequent tests.
100
+
101
+
### Procedure
102
+
103
+
When adding `@functools.cache` to a function:
104
+
105
+
1. Import the function at the top of `tests/conftest.py`.
106
+
2. Add a `<function_name>.cache_clear()` call in the body of the `clear_functools_caches` autouse fixture.
107
+
108
+
### Why
109
+
110
+
The `clear_functools_caches` autouse fixture runs before each test, ensuring every test starts with a clean cache. Without this registration, a test that triggers caching will leave stale values in memory that silently affect subsequent tests, causing order-dependent failures that are hard to diagnose.
0 commit comments