From 8e1debd5ed6cb0fe5737c59682fb0036d79c29f5 Mon Sep 17 00:00:00 2001 From: konsisumer Date: Wed, 29 Jul 2026 21:44:13 -0700 Subject: [PATCH] docs: purge stale xdist/_enforce_test_timeout test-runner references repo-wide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test runner moved to per-file subprocess isolation via scripts/run_tests_parallel.py (hermetic `env -i`, worker count auto-scaled from CPU count, FLAKY-retry policy) — no pytest-xdist, no SIGALRM per-test timeout fixture. Docs still described the old runner in many places: - AGENTS.md: "-n auto xdist workers, in-tree subprocess-isolation plugin" clause replaced with the current per-file-subprocess description; the `::test_x` single-test example now shows file + -k (runner is file-granular). - CONTRIBUTING.md: "hermetic env, 4 xdist workers" comment corrected; `tests/conftest.py::_enforce_test_timeout` reference redirected to the win32 timeout-method shim in `tests/conftest.py::pytest_configure`. - skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md and windows-quirks.md: same corrections (the bundled skill mirrors the contributor docs); Windows workaround no longer installs pytest-xdist or passes -n 0. - website/docs + zh-Hans i18n mirrors: same fixes in adding-providers.md and the bundled-skill doc pages. - skills/software-development/python-debugpy/SKILL.md (+ zh-Hans mirror): "-p no:xdist"/"-n 0" pdb advice rewritten for the captured per-file subprocess runner. - skills/creative/comfyui/tests/README.md: parent-repo "-n auto by default" rationale updated to past tense. Combined salvage of PR #38295 (konsisumer), PR #51354 (TutkuEroglu, redirected to the current conftest truth and the relocated references/contributor-guide.md), and PR #54956 (waroffchange). Co-authored-by: TutkuEroglu Co-authored-by: waroffchange <116298975+waroffchange@users.noreply.github.com> --- AGENTS.md | 5 +++-- CONTRIBUTING.md | 5 +++-- .../references/contributor-guide.md | 7 ++++--- .../hermes-agent/references/windows-quirks.md | 9 +++++---- skills/creative/comfyui/tests/README.md | 12 +++++++----- .../python-debugpy/SKILL.md | 16 +++++++--------- .../docs/developer-guide/adding-providers.md | 4 ++-- .../developer-guide/adding-providers.md | 4 ++-- .../autonomous-ai-agents-hermes-agent.md | 18 +++++++++--------- .../software-development-python-debugpy.md | 16 +++++++--------- 10 files changed, 49 insertions(+), 47 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d623ba59bbf..70fc9bc8d64 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1284,14 +1284,15 @@ def profile_env(tmp_path, monkeypatch): ### Python **ALWAYS use `scripts/run_tests.sh`** — do not call `pytest` directly. The script enforces hermetic environment parity with CI (unset credential vars, TZ=UTC, LANG=C.UTF-8, -`-n auto` xdist workers, in-tree subprocess-isolation plugin). Direct `pytest` +per-file subprocess isolation via `scripts/run_tests_parallel.py` — no xdist, +worker count auto-scaled from CPU count). Direct `pytest` on a 16+ core developer machine with API keys set diverges from CI in ways that have caused multiple "works locally, fails in CI" incidents (and the reverse). ```bash scripts/run_tests.sh # full suite, CI-parity scripts/run_tests.sh tests/gateway/ # one directory -scripts/run_tests.sh tests/agent/test_foo.py::test_x # one test +scripts/run_tests.sh tests/agent/test_foo.py -k test_x # one test (file + -k; the runner is file-granular) scripts/run_tests.sh -v --tb=long # pass-through pytest flags ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 46581d82003..4fbf5b5a3da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -201,7 +201,8 @@ ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes ### Run tests ```bash -# Preferred — matches CI (hermetic env, 4 xdist workers); see AGENTS.md +# Preferred — matches CI (hermetic `env -i`, per-file subprocess isolation +# via run_tests_parallel.py, worker count auto-scaled); see AGENTS.md scripts/run_tests.sh # Alternative (activate the venv first). The wrapper is still recommended @@ -848,7 +849,7 @@ that touches the OS, assume *any* platform can hit your code path. Tests that use POSIX-only syscalls need a skip marker. Common ones: - Symlinks → `@pytest.mark.skipif(sys.platform == "win32", ...)` - `0o600` file modes → `@pytest.mark.skipif(sys.platform.startswith("win"), ...)` -- `signal.SIGALRM` → Unix-only (see `tests/conftest.py::_enforce_test_timeout`) +- `signal.SIGALRM` → Unix-only (per-test timeouts no longer use it directly; see the win32 timeout-method shim in `tests/conftest.py::pytest_configure`) - `os.setsid` / `os.fork` → Unix-only - Live Winsock / Windows-specific regression tests → `@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")` diff --git a/skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md b/skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md index 3bda9021185..a578f06d25c 100644 --- a/skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md +++ b/skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md @@ -84,8 +84,9 @@ run_conversation(): ### Testing -Use the canonical runner — it enforces CI-parity (hermetic env, unset -credentials, TZ=UTC, xdist workers, per-test subprocess isolation): +Use the canonical runner — it enforces CI-parity (hermetic `env -i`, unset +credentials, TZ=UTC, per-file subprocess isolation via +`scripts/run_tests_parallel.py` — no xdist, worker count auto-scaled): ```bash scripts/run_tests.sh # full suite @@ -102,7 +103,7 @@ scripts/run_tests.sh -v --tb=long # pass-through pytest flags **Cross-platform test guards:** tests using POSIX-only syscalls need a skip marker. Common ones already in the codebase: - Symlink creation → `@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows")` (see `tests/cron/test_cron_script.py`) - POSIX file modes (0o600, etc.) → `@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows")` (see `tests/hermes_cli/test_auth_toctou_file_modes.py`) -- `signal.SIGALRM` → Unix-only (see `tests/conftest.py::_enforce_test_timeout`) +- `signal.SIGALRM` → Unix-only (per-test timeouts no longer use it directly; see the win32 timeout-method shim in `tests/conftest.py::pytest_configure`) - Live Winsock / Windows-specific regression tests → `@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")` **Monkeypatching `sys.platform` is not enough** when the code under test also calls `platform.system()` / `platform.release()` / `platform.mac_ver()`. Those functions re-read the real OS independently, so a test that sets `sys.platform = "linux"` on a Windows runner will still see `platform.system() == "Windows"` and route through the Windows branch. Patch all three together: diff --git a/skills/autonomous-ai-agents/hermes-agent/references/windows-quirks.md b/skills/autonomous-ai-agents/hermes-agent/references/windows-quirks.md index 4cf283e9533..d87f1c0eb5b 100644 --- a/skills/autonomous-ai-agents/hermes-agent/references/windows-quirks.md +++ b/skills/autonomous-ai-agents/hermes-agent/references/windows-quirks.md @@ -33,13 +33,14 @@ echo `os.environ` inside an `execute_code` block to confirm `SYSTEMROOT` is set. `scripts/run_tests.sh` is POSIX-only (expects `.venv/bin/activate`); the Hermes-installed `venv/Scripts/` has no pip/pytest (stripped for size). -Install pytest into a system Python and run directly with `-n 0` -(`pyproject.toml`'s `addopts` already sets `-n`): +Install pytest into a system Python and run directly (the repo no longer +uses pytest-xdist; the canonical runner does per-file subprocess isolation, +which the POSIX-only wrapper handles): ```bash -"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml +"/c/Program Files/Python311/python" -m pip install --user pytest pyyaml export PYTHONPATH="$(pwd)" -"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0 +"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short ``` (POSIX-only tests need skip guards — see the cross-platform guard list in diff --git a/skills/creative/comfyui/tests/README.md b/skills/creative/comfyui/tests/README.md index 833632ae9c4..d27fa97e32a 100644 --- a/skills/creative/comfyui/tests/README.md +++ b/skills/creative/comfyui/tests/README.md @@ -43,8 +43,10 @@ When you change a script: ## Why the explicit `-c` / `-o`? -The parent hermes-agent repo's `pyproject.toml` enables `pytest-xdist` by -default (`-n auto`). This suite is small enough that parallelism isn't -worth the complexity, and pytest-xdist isn't always installed in the user's -environment. The `-c tests/pytest.ini -o addopts="-p no:xdist"` flags make -the suite run identically regardless of the parent project's config. +The parent hermes-agent repo used to enable `pytest-xdist` by default +(`-n auto`); the canonical runner has since moved to per-file subprocess +isolation via `scripts/run_tests_parallel.py` and no longer uses xdist. +This suite is small enough that parallelism isn't worth the complexity, and +pytest-xdist isn't always installed in the user's environment. The +`-c tests/pytest.ini -o addopts="-p no:xdist"` flags make the suite run +identically regardless of the parent project's config. diff --git a/skills/software-development/python-debugpy/SKILL.md b/skills/software-development/python-debugpy/SKILL.md index e57d8d91e25..9907afdac1d 100644 --- a/skills/software-development/python-debugpy/SKILL.md +++ b/skills/software-development/python-debugpy/SKILL.md @@ -107,11 +107,9 @@ scripts/run_tests.sh tests/path/to/test_file.py::test_name --trace scripts/run_tests.sh tests/path/to/test_file.py --showlocals --tb=long ``` -Note: `scripts/run_tests.sh` uses xdist (`-n 4`) by default, and pdb does NOT work under xdist. Add `-p no:xdist` or run a single test with `-n 0`: +Note: `scripts/run_tests.sh` runs each test file in a captured subprocess via `run_tests_parallel.py` (no xdist), so interactive pdb does NOT work under the wrapper. Run pytest directly for `--pdb`: ```bash -scripts/run_tests.sh tests/foo_test.py::test_bar --pdb -p no:xdist -# or source .venv/bin/activate python -m pytest tests/foo_test.py::test_bar --pdb ``` @@ -276,7 +274,7 @@ nc 127.0.0.1 4444 ## Debugging Hermes-specific Processes ### Tests -See Recipe 3. Always add `-p no:xdist` or run single tests without xdist. +See Recipe 3. The wrapper captures subprocess output, so run pytest directly for interactive pdb. ### `run_agent.py` / CLI — one-shot Easiest: add `breakpoint()` near the suspect line, then run `hermes` normally. Control returns to your terminal at the pause point. @@ -308,7 +306,7 @@ Long-lived. Use `remote-pdb` at a handler, or `debugpy` with `--wait-for-client` ## Common Pitfalls -1. **pdb under pytest-xdist silently does nothing.** You won't see the prompt, the test just hangs. Always use `-p no:xdist` or `-n 0`. +1. **pdb under a parallel/output-capturing runner silently does nothing.** You won't see the prompt, the test just hangs (true of pytest-xdist and of `scripts/run_tests.sh`'s captured per-file subprocesses). Run pytest directly on a single file for interactive debugging. 2. **`breakpoint()` in CI / non-TTY contexts hangs the process.** Safe locally; never commit it. Add a pre-commit grep as a safety net. @@ -333,7 +331,7 @@ Long-lived. Use `remote-pdb` at a handler, or `debugpy` with `--wait-for-client` - [ ] After `pip install debugpy`, confirm: `python -c "import debugpy; print(debugpy.__version__)"` - [ ] For remote debug, confirm the port is actually listening: `ss -tlnp | grep 5678` -- [ ] First breakpoint actually hits (if it doesn't, you likely have `PYTHONBREAKPOINT=0`, you're under xdist, or execution finished before attach) +- [ ] First breakpoint actually hits (if it doesn't, you likely have `PYTHONBREAKPOINT=0`, you're under a parallel/capturing runner, or execution finished before attach) - [ ] `where` / `w` shows the expected call stack - [ ] Post-debug cleanup: no stray `breakpoint()` / `set_trace()` in committed code ```bash @@ -354,10 +352,10 @@ breakpoint() **"This test passes in isolation but fails in the suite."** ```bash -scripts/run_tests.sh tests/the_test.py --pdb -p no:xdist -# But if it only fails WITH other tests: +scripts/run_tests.sh tests/the_test.py # confirm it fails under the isolated runner first +# For interactive debugging, or if it only fails WITH other tests: source .venv/bin/activate -python -m pytest tests/ -x --pdb -p no:xdist +python -m pytest tests/ -x --pdb # Now it pdb-traps at the exact failing test after state accumulated. ``` diff --git a/website/docs/developer-guide/adding-providers.md b/website/docs/developer-guide/adding-providers.md index 0898d698ac8..1964c194629 100644 --- a/website/docs/developer-guide/adding-providers.md +++ b/website/docs/developer-guide/adding-providers.md @@ -338,11 +338,11 @@ For docs-only examples, the exact file set may differ. The point is to cover: - provider:model parsing - any adapter-specific message conversion -Run tests with xdist disabled: +Run the targeted tests (or use `scripts/run_tests.sh`, which runs each file in its own subprocess): ```bash source venv/bin/activate -python -m pytest tests/hermes_cli/test_runtime_provider_resolution.py tests/cli/test_cli_provider_resolution.py tests/hermes_cli/test_setup_model_provider.py tests/run_agent/test_provider_parity.py -n0 -q +python -m pytest tests/hermes_cli/test_runtime_provider_resolution.py tests/cli/test_cli_provider_resolution.py tests/hermes_cli/test_setup_model_provider.py tests/run_agent/test_provider_parity.py -q ``` For deeper changes, run the full suite before pushing: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-providers.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-providers.md index 04245b32e1c..638f47df2e7 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-providers.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-providers.md @@ -338,11 +338,11 @@ Prompt(提示词)缓存和 provider 专属的调节项很容易出现回归 - `provider:model` 解析 - 任何适配器专属的消息转换 -使用禁用 xdist 的方式运行测试: +运行目标测试(或使用 `scripts/run_tests.sh`,它在独立子进程中运行每个文件): ```bash source venv/bin/activate -python -m pytest tests/test_runtime_provider_resolution.py tests/test_cli_provider_resolution.py tests/test_cli_model_command.py tests/test_setup_model_selection.py -n0 -q +python -m pytest tests/test_runtime_provider_resolution.py tests/test_cli_provider_resolution.py tests/test_cli_model_command.py tests/test_setup_model_selection.py -q ``` 对于更深层的修改,在推送前运行完整测试套件: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md index 986eb015d48..c18bb063ce2 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md @@ -698,20 +698,20 @@ mintty / git-bash 行为相同(Alt+Enter 全屏),除非你在选项 → ### 测试/贡献 -**`scripts/run_tests.sh` 在 Windows 上无法直接使用** — 它查找 POSIX venv 布局(`.venv/bin/activate`)。Hermes 安装的 venv 位于 `venv/Scripts/`,也没有 pip 或 pytest(为减小安装体积而精简)。解决方案:将 `pytest + pytest-xdist + pyyaml` 安装到系统 Python 3.11 用户站点,然后设置 `PYTHONPATH` 直接调用 pytest: +**`scripts/run_tests.sh` 在 Windows 上无法直接使用** — 它查找 POSIX venv 布局(`.venv/bin/activate`)。Hermes 安装的 venv 位于 `venv/Scripts/`,也没有 pip 或 pytest(为减小安装体积而精简)。解决方案:将 `pytest + pyyaml` 安装到系统 Python 3.11 用户站点,然后设置 `PYTHONPATH` 直接调用 pytest: ```bash -"/c/Program Files/Python311/python" -m pip install --user pytest pytest-xdist pyyaml +"/c/Program Files/Python311/python" -m pip install --user pytest pyyaml export PYTHONPATH="$(pwd)" -"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short -n 0 +"/c/Program Files/Python311/python" -m pytest tests/foo/test_bar.py -v --tb=short ``` -使用 `-n 0` 而非 `-n 4` — `pyproject.toml` 的默认 `addopts` 已包含 `-n`,且 wrapper 的 CI 一致性保证不适用于非 POSIX 环境。 +仓库已不再使用 pytest-xdist——规范 runner 通过 `run_tests_parallel.py` 做按文件子进程隔离,但该 wrapper 仅支持 POSIX,其 CI 一致性保证不适用于非 POSIX 环境。 **仅 POSIX 的测试需要跳过守卫。** 代码库中已有的常见标记: - 符号链接——Windows 上需要提升权限 - `0o600` 文件模式——POSIX 模式位在 NTFS 上默认不强制执行 -- `signal.SIGALRM`——仅 Unix(参见 `tests/conftest.py::_enforce_test_timeout`) +- `signal.SIGALRM`——仅 Unix(每测试超时不再直接使用它;参见 `tests/conftest.py::pytest_configure` 中的 win32 timeout-method shim) - Winsock / Windows 特有回归——`@pytest.mark.skipif(sys.platform != "win32", ...)` 使用现有的跳过模式风格(`sys.platform == "win32"` 或 `sys.platform.startswith("win")`)以与测试套件其余部分保持一致。 @@ -891,19 +891,19 @@ python -m pytest tests/tools/ -q # 特定区域 - 推送任何变更前运行完整套件 - 使用 `-o 'addopts='` 清除任何内置的 pytest 标志 -**Windows 贡献者:** `scripts/run_tests.sh` 目前查找 POSIX venv(`.venv/bin/activate` / `venv/bin/activate`),在 Windows 上会报错,因为布局是 `venv/Scripts/activate` + `python.exe`。Hermes 安装的 venv 位于 `venv/Scripts/`,也没有 `pip` 或 `pytest`——为终端用户安装体积而精简。解决方案:将 pytest + pytest-xdist + pyyaml 安装到系统 Python 3.11 用户站点(`/c/Program Files/Python311/python -m pip install --user pytest pytest-xdist pyyaml`),然后直接运行测试: +**Windows 贡献者:** `scripts/run_tests.sh` 目前查找 POSIX venv(`.venv/bin/activate` / `venv/bin/activate`),在 Windows 上会报错,因为布局是 `venv/Scripts/activate` + `python.exe`。Hermes 安装的 venv 位于 `venv/Scripts/`,也没有 `pip` 或 `pytest`——为终端用户安装体积而精简。解决方案:将 pytest + pyyaml 安装到系统 Python 3.11 用户站点(`/c/Program Files/Python311/python -m pip install --user pytest pyyaml`),然后直接运行测试: ```bash export PYTHONPATH="$(pwd)" -"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short -n 0 +"/c/Program Files/Python311/python" -m pytest tests/tools/test_foo.py -v --tb=short ``` -使用 `-n 0`(而非 `-n 4`),因为 `pyproject.toml` 的默认 `addopts` 已包含 `-n`,且 wrapper 的 CI 一致性保证不适用于非 POSIX 环境。 +仓库已不再使用 pytest-xdist——规范 runner 通过 `run_tests_parallel.py` 做按文件子进程隔离,但该 wrapper 仅支持 POSIX,其 CI 一致性保证不适用于非 POSIX 环境。 **跨平台测试守卫:** 使用仅 POSIX 系统调用的测试需要跳过标记。代码库中已有的常见标记: - 符号链接创建 → `@pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require elevated privileges on Windows")`(参见 `tests/cron/test_cron_script.py`) - POSIX 文件模式(0o600 等)→ `@pytest.mark.skipif(sys.platform.startswith("win"), reason="POSIX mode bits not enforced on Windows")`(参见 `tests/hermes_cli/test_auth_toctou_file_modes.py`) -- `signal.SIGALRM` → 仅 Unix(参见 `tests/conftest.py::_enforce_test_timeout`) +- `signal.SIGALRM` → 仅 Unix(每测试超时不再直接使用它;参见 `tests/conftest.py::pytest_configure` 中的 win32 timeout-method shim) - 实时 Winsock / Windows 特有回归测试 → `@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")` **仅 monkeypatch `sys.platform` 是不够的**,当被测代码还调用 `platform.system()` / `platform.release()` / `platform.mac_ver()` 时。这些函数独立重新读取真实 OS,因此在 Windows runner 上将 `sys.platform = "linux"` 的测试仍会看到 `platform.system() == "Windows"` 并走 Windows 分支。需要同时 patch 三者: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/software-development/software-development-python-debugpy.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/software-development/software-development-python-debugpy.md index a8276c5678f..e3ea93f47b4 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/software-development/software-development-python-debugpy.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/software-development/software-development-python-debugpy.md @@ -125,11 +125,9 @@ scripts/run_tests.sh tests/path/to/test_file.py::test_name --trace scripts/run_tests.sh tests/path/to/test_file.py --showlocals --tb=long ``` -注意:`scripts/run_tests.sh` 默认使用 xdist(`-n 4`),pdb 在 xdist 下**无法正常工作**。请添加 `-p no:xdist` 或使用 `-n 0` 运行单个测试: +注意:`scripts/run_tests.sh` 通过 `run_tests_parallel.py` 将每个测试文件放在捕获输出的子进程中运行(不使用 xdist),因此交互式 pdb 在 wrapper 下**无法正常工作**。请直接运行 pytest 使用 `--pdb`: ```bash -scripts/run_tests.sh tests/foo_test.py::test_bar --pdb -p no:xdist -# 或 source .venv/bin/activate python -m pytest tests/foo_test.py::test_bar --pdb ``` @@ -294,7 +292,7 @@ nc 127.0.0.1 4444 ## 调试 Hermes 特定进程 ### 测试 -参见方案 3。始终添加 `-p no:xdist` 或在不使用 xdist 的情况下运行单个测试。 +参见方案 3。wrapper 会捕获子进程输出,交互式 pdb 请直接运行 pytest。 ### `run_agent.py` / CLI — 一次性运行 最简单:在可疑行附近添加 `breakpoint()`,然后正常运行 `hermes`。控制权将在暂停点返回到你的终端。 @@ -326,7 +324,7 @@ set_trace(host="127.0.0.1", port=4444) # 在你想捕获的 RPC 处理器中 ## 常见陷阱 -1. **pdb 在 pytest-xdist 下静默失效。** 你不会看到提示符,测试只会挂起。始终使用 `-p no:xdist` 或 `-n 0`。 +1. **pdb 在并行/捕获输出的 runner 下静默失效。** 你不会看到提示符,测试只会挂起(pytest-xdist 与 `scripts/run_tests.sh` 的按文件捕获子进程均如此)。交互式调试请直接对单个文件运行 pytest。 2. **`breakpoint()` 在 CI / 非 TTY 环境中会挂起进程。** 本地使用没问题;永远不要提交它。添加 pre-commit grep 作为安全网。 @@ -351,7 +349,7 @@ set_trace(host="127.0.0.1", port=4444) # 在你想捕获的 RPC 处理器中 - [ ] `pip install debugpy` 后确认:`python -c "import debugpy; print(debugpy.__version__)"` - [ ] 对于远程调试,确认端口确实在监听:`ss -tlnp | grep 5678` -- [ ] 第一个断点确实触发(如果没有,可能是 `PYTHONBREAKPOINT=0`、在 xdist 下运行,或执行在附加前已结束) +- [ ] 第一个断点确实触发(如果没有,可能是 `PYTHONBREAKPOINT=0`、在并行/捕获输出的 runner 下运行,或执行在附加前已结束) - [ ] `where` / `w` 显示预期的调用栈 - [ ] 调试后清理:已提交代码中无残留的 `breakpoint()` / `set_trace()` / `debugpy.listen` ```bash @@ -372,10 +370,10 @@ breakpoint() **"这个测试单独运行通过,但在测试套件中失败。"** ```bash -scripts/run_tests.sh tests/the_test.py --pdb -p no:xdist -# 但如果只有与其他测试一起运行才失败: +scripts/run_tests.sh tests/the_test.py # 先确认它在隔离 runner 下失败 +# 交互式调试,或只有与其他测试一起运行才失败时: source .venv/bin/activate -python -m pytest tests/ -x --pdb -p no:xdist +python -m pytest tests/ -x --pdb # 现在它会在状态积累后的确切失败测试处触发 pdb。 ```