deer-flow/backend/tests/AGENTS.md
Xinmin Zeng 2a97ec3e58
docs: turn README into an index and move reference detail to docs/guide (#8113)
* docs: turn README into an index and move reference detail to docs/guide

The README had grown to 393 KB because every change appended its notes there. The text moves verbatim into 18 topic guides under docs/guide/; only headings are re-leveled and relative links re-pointed. The README keeps the introduction, a quick start and a guide index. Contributor test notes move to CONTRIBUTING.md.

* docs: send user docs to topic guides and budget the root README

The rule 'update README.md for user-facing changes' is what grew the README. Guidance now points to docs/guide/, and check_agent_guidance.py fails when the root README exceeds 16 KiB (AG003).

* chore: remove unreferenced screenshots and finished plan notes

pr-build/ holds two PR screenshots (3 MB) from #1986. plans/ holds the plan for the merged #4049. docs/SKILL_NAME_CONFLICT_FIX.md is a February change note. Nothing references them.

* docs: route always-loaded AGENTS.md files to scoped guides

* docs(agents): cut scoped guides to scope, verify, traps, decisions

Each AGENTS.md keeps four kinds of content: the scope of the directory, the
verification commands, traps a local test run does not show, and decisions the
code cannot state. Values, field lists, function inventories, test names, issue
numbers and history are deleted, because the code, the tests and git state them.

Search and fetch providers share one community guide. Four guides with no
remaining content are removed. The size check now allows 6 KiB per file (hard
limit 8 KiB) and 24 KiB per chain (hard limit 32 KiB).

* style: format frontend guide table and guidance test imports

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-11 13:26:17 +08:00

77 lines
3.7 KiB
Markdown

# Backend tests (`backend/tests/`)
The offline suite for the Gateway and the harness. `blocking_io/` is the strict
event-loop gate, `support/` holds shared helpers, and `fixtures/` holds recorded
data. What a single test file covers is stated in that file, not here.
## Verify
```bash
cd backend
make test # four offline shards; TEST_JOBS=1 runs serially
make test-blocking-io # strict gate over tests/blocking_io/
python -m pytest tests/test_<feature>.py::test_<name> -q
```
Live tests run only with `DEER_FLOW_RUN_LIVE_TESTS=1`. PostgreSQL cases run when
`TEST_POSTGRES_URI` is set and skip otherwise. Helm and real-Compose cases skip
with a reason when the binary is missing.
## What a test must exercise
- **Run the production path.** Drive the real graph, worker, repository, script
or HTTP client, and replace only the outermost boundary: the model response,
the network transport, the clock. A test that raises the expected error itself
or writes the stored result directly proves nothing about the code.
- **Put the double below the SDK.** A fake HTTP transport under the real vendor
client checks the payload that DeerFlow sends. A mocked client method does not.
- **A regression test fails on the unfixed code.** Check that before you commit
the fix. Do not encode a known bug as expected behaviour, and do not hide it
behind a permanent `xfail`.
- **Assert on structure.** Check decoded payloads, stored rows and metadata.
User-facing wording is asserted only where the wording is the contract.
- **Scripts run as copies in a temporary checkout.** Never swap sources in the
working tree during a test, and never let a test read the developer's own
`config.yaml`, `.env` or runtime home.
## Concurrency and timing
- **Synchronize with events and barriers.** A sleep or a timing threshold passes
on a fast machine and fails on a loaded CI runner. Park the code at a named
point, observe the peer reach it, then release.
- **Use a controlled clock** for leases, expiry and scheduling.
- **Release everything in `finally`.** Blocked workers, paused tasks, patched
process-wide state and event loops are restored even when the assertion fails.
A leaked worker fails a later, unrelated test.
- **Treat an unhandled warning from a worker thread as an error.**
- **Injected failures must be shown to fire.** Assert that the injection ran, so
a refactor cannot turn a failure test into a silent pass.
## Portability
- **Use the helpers in `support/`.** `support.postgres` builds the isolated schema
URL, `support.symlinks.symlink_or_skip` handles hosts without symlink rights,
`support.shell` finds a POSIX shell or Git Bash, and `support.compose` detects
the Compose version.
- **Guard POSIX-only cases with `os.name`** so that Windows collection succeeds.
Permission tests also skip as root, where mode bits do not restrict access.
- **Write fixtures with an explicit newline mode and encoding.** Platform
defaults change LF/CRLF hashes and non-ASCII paths.
- **Do not import another test module's private fixtures.** Shared code moves to
`support/` or `conftest.py`.
- **Circular imports are solved in `conftest.py`** with a `sys.modules` stub; see
the existing entry for `deerflow.subagents.executor`.
## Blocking-I/O tests
Every test under `blocking_io/` runs with a detector that fails on a blocking
call made on the event loop through DeerFlow code. Add a case there when you add
an async entry point that touches files, subprocesses or a synchronous SDK.
`@pytest.mark.allow_blocking_io` is for a test that needs the unguarded behaviour
and states why.
## Guidance inventory
When you add a scoped `AGENTS.md`, add its path to `EXPECTED_GUIDANCE_PATHS` in
`test_agent_guidance_check.py` in the same change.