Skip to content

Commit 8242ceb

Browse files
timsaucerclaude
andcommitted
docs: record the Python-first testing preference in AGENTS.md
New coverage should land as a doctest example or a pytest case. Agents have been adding Rust tests that CI never executes: no workflow invokes `cargo test`, and `cargo clippy --all-targets` only compiles the test code. Write down that constraint, along with the reason a `cargo test` job is not a trivial addition, so the tradeoff does not have to be rediscovered. Also point at the FFI example suites, which are easy to overlook when judging whether behavior is reachable from Python. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 1d30a71 commit 8242ceb

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,40 @@ pre-commit run --all-files
6262

6363
Fix any failures before committing.
6464

65+
## Test Coverage
66+
67+
Always prefer Python coverage — a doctest example in a docstring, or a pytest
68+
case. The user-facing Python surface is the first line of defense and the
69+
primary focus, so behavior should be pinned where users actually meet it.
70+
71+
**CI does not run Rust tests.** No workflow invokes `cargo test`; the only
72+
Rust checks are `cargo fmt --check` and
73+
`cargo clippy --no-deps --all-targets`. `--all-targets` compiles
74+
`#[cfg(test)]` code, so a Rust test cannot rot into a non-compiling state, but
75+
it is never executed and a behavioral regression will not fail the build. A
76+
Rust test added today is dead weight.
77+
78+
Adding a `cargo test` job is not a one-line change: `crates/core/Cargo.toml`
79+
enables `pyo3/extension-module` unconditionally, so the test binary fails to
80+
link against `Py_*` symbols on Linux. The feature would have to be gated first.
81+
82+
Write a Rust test only when the behavior is genuinely unreachable from Python,
83+
and wire up CI in the same change so it actually runs. Before concluding it is
84+
unreachable, check the suites that already exist:
85+
86+
- `python/tests/` — the main suite. Run `pytest python/`, **not**
87+
`pytest python/tests/`: `--doctest-modules` is on by default and the
88+
narrower path skips the doctests in `python/datafusion/`.
89+
- `examples/datafusion-ffi-example/python/tests/` and
90+
`examples/datafusion-ffi-query-planner-example/python/tests/` — integration
91+
coverage across a real FFI boundary, for anything involving extension
92+
codecs, table providers, query planners, or capsule export. These need the
93+
example crates built (`maturin build`, then install the wheel).
94+
- `examples/tpch/` — end-to-end query coverage.
95+
96+
Prefer asserting observable behavior over internal accessors. A test that
97+
checks a getter can pass while the path a user actually takes is broken.
98+
6599
## Python Function Docstrings
66100

67101
Every Python function must include a docstring with usage examples.

0 commit comments

Comments
 (0)