Type: Performance Issue
Behaviour
I asked Claude (Anthropic's Claude Code) to investigate this and put together a minimal repro. The rest of this section is its summary.
Every test run started from the Test Explorer / gutter "run" button takes about 5 seconds longer than the pytest subprocess itself needs. The Testing view's spinner keeps spinning for that extra ~5s after the actual test run has already finished, before the run can be started again.
With the Python extension's log level set to Trace, the Python output channel shows the same pattern on every single run (not intermittently):
15:35:34.037 [debug] Test run finished, subprocess closed.
15:35:39.039 [debug] awaitDeferredWithTimeout: deferred did not settle within 5000ms; giving up and continuing.
15:35:39.040 [debug] Finished running tests, ending runInstance.
The pytest subprocess exits at .037, and exactly 5000ms later (.039) awaitDeferredWithTimeout gives up and the run is finally marked finished. This 5000ms gap is identical on every run.
Looking at the bundled extension source (out/client/extension.js), the pytest execution adapter always does, in a finally block after the run:
finally { await awaitDeferredWithTimeout(deferred, RESULT_PIPE_DRAIN_TIMEOUT_MS) }
where RESULT_PIPE_DRAIN_TIMEOUT_MS = 5000 is hardcoded (no user-facing setting), and:
t.awaitDeferredWithTimeout = async function (e, t) {
let n;
try {
await Promise.race([
e.promise,
new Promise((e) => {
n = setTimeout(() => {
traceVerbose(`awaitDeferredWithTimeout: deferred did not settle within ${t}ms; giving up and continuing.`);
e();
}, t);
}),
]);
} finally {
n && clearTimeout(n);
}
};
The deferred is only resolved from inside the results named-pipe wrapper's own dispose() callback (startRunResultNamedPipe, same file), which is expected to fire when the pipe reports a clean end-of-stream/drain. In this environment that resolution never arrives before the 5s timeout, so every run falls through to the "give up and continue" branch and eats the full 5 seconds on top of the real test time.
On the Python side (python_files/vscode_pytest/__init__.py), the writer end of the results pipe is only closed via:
atexit.register(lambda: __writer.close() if __writer else None)
i.e. it relies on full interpreter shutdown to close the pipe, rather than closing/flushing the connection proactively right after the last result is written. This looks like the likely reason the "drain" signal the extension is waiting on doesn't arrive in time, making the 5s timeout the common case rather than a rare fallback.
For a fast test suite (a few seconds or less), this hardcoded wait dominates the total run time and makes iterating on individual tests via the Test Explorer noticeably slower than running pytest directly from a terminal.
Steps to reproduce:
- Open a workspace with
python.testing.pytestEnabled: true and at least one pytest test.
- Set the Python extension log level to
Trace (Command Palette → Developer: Set Log Level... → Python).
- Run any test from the Testing view or the gutter icon.
- Watch the Testing view spinner and the
Python output channel: the spinner keeps spinning for ~5s after "Test run finished, subprocess closed." is logged, until awaitDeferredWithTimeout gives up.
Diagnostic data
Output for Python in the Output panel (View→Output, change the drop-down the upper-right of the Output panel to Python)
2026-07-28 15:35:31.813 [debug] Starting Test Result named pipe
2026-07-28 15:35:31.813 [debug] Test Results named pipe /run/user/1001/python-test-results-a573e256a741ea7b46bd connected
2026-07-28 15:35:31.814 [debug] Executable path for pytest execution: /path/to/workspace/.venv/bin/python.
2026-07-28 15:35:31.814 [info] arg: --rootdir already exists in args, not adding.
2026-07-28 15:35:31.814 [info] Attempting to use temp directory for test ids file, file name: test-ids-1acf8ccdcb1412644b52.txt
2026-07-28 15:35:31.828 [info] Environment variables set for pytest execution: PYTHONPATH=/path/to/.vscode/extensions/ms-python.python-2026.5.2026070801-linux-x64/python_files:./, TEST_RUN_PIPE=/run/user/1001/python-test-results-a573e256a741ea7b46bd, RUN_TEST_IDS_PIPE=/run/user/1001/test-ids-1acf8ccdcb1412644b52.txt
2026-07-28 15:35:31.829 [info] Running pytest with arguments: /path/to/.vscode/extensions/ms-python.python-2026.5.2026070801-linux-x64/python_files/vscode_pytest/run_pytest_script.py --rootdir=/path/to/workspace for workspace /path/to/workspace
2026-07-28 15:35:31.829 [info] > ./.venv/bin/python ~/.vscode/extensions/ms-python.python-2026.5.2026070801-linux-x64/python_files/vscode_pytest/run_pytest_script.py --rootdir=.
2026-07-28 15:35:31.829 [info] cwd: .
2026-07-28 15:35:33.544 [debug] Test Result named pipe /run/user/1001/python-test-results-a573e256a741ea7b46bd received data
2026-07-28 15:35:34.037 [debug] Test run finished, subprocess closed.
2026-07-28 15:35:39.039 [debug] awaitDeferredWithTimeout: deferred did not settle within 5000ms; giving up and continuing.
2026-07-28 15:35:39.040 [debug] Finished running tests, ending runInstance.
Environment
- VS Code Version: 1.130.0
- Python Extension Version: 2026.5.2026070801
- OS Version: Debian GNU/Linux 13 (trixie), kernel 6.12.96+deb13-amd64, x86_64
- Python interpreter: 3.14.6 (CPython, uv-managed virtualenv,
.venv)
- Test framework: pytest 9.1.1
Extension version: 2026.5.2026070801
VS Code version: Code 1.130.0 (1b6a188127eeaf9194f945eb6eb89a657e93c54c, 2026-07-22T14:55:04Z)
OS version: Linux x64 6.12.96+deb13-amd64
Modes:
- Python version (& distribution if applicable, e.g. Anaconda): 3.14.6
- Type of virtual environment used (e.g. conda, venv, virtualenv, etc.): Venv
- Value of the
python.languageServer setting: None
User Settings
languageServer: "None"
testing
• pytestArgs: "<placeholder>"
• pytestEnabled: true
Installed Extensions
| Extension Name |
Extension Id |
Version |
| copilot-chat |
Git |
0.58.0 |
| debugpy |
ms- |
2026.7.12081008 |
| docker |
doc |
0.18.0 |
| js-debug |
ms- |
1.117.0 |
| js-debug-companion |
ms- |
1.1.3 |
| jsts-chat-features |
Typ |
0.0.4 |
| jupyter |
ms- |
2026.6.2026071501 |
| jupyter-keymap |
ms- |
1.1.2 |
| jupyter-renderers |
ms- |
1.3.2025062701 |
| python |
ms- |
2026.5.2026070801 |
| ruff |
cha |
2026.66.0 |
| ty |
ast |
2026.64.0 |
| vscode-containers |
ms- |
2.4.5 |
| vscode-cython |
ktn |
1.0.3 |
| vscode-js-profile-table |
ms- |
1.0.10 |
| vscode-python-envs |
ms- |
1.37.2026072401 |
System Info
| Item |
Value |
| CPUs |
Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz (8 x 3399) |
| GPU Status |
2d_canvas: enabled GPU0: VENDOR= 0x8086 [Google Inc. (Intel)], DEVICE=0x9b41 [ANGLE (Intel, Mesa Intel(R) UHD Graphics (CML GT2), OpenGL ES 3.2 Mesa 25.0.7-2+deb13u1)], DRIVER_VENDOR=Mesa, DRIVER_VERSION=25.0.7 ACTIVE Machine model name: Machine model version: direct_rendering_display_compositor: disabled_off_ok gpu_compositing: enabled multiple_raster_threads: enabled_on opengl: enabled_on rasterization: enabled raw_draw: disabled_off_ok skia_graphite: disabled_off trees_in_viz: disabled_off video_decode: enabled video_encode: disabled_software vulkan: disabled_off webgl: enabled webgpu: enabled webgpu_on_vk_via_gl_interop: disabled_off webnn: disabled_off |
| Load (avg) |
0, 0, 0 |
| Memory (System) |
15.32GB (11.51GB free) |
| Process Argv |
. |
| Screen Reader |
no |
| VM |
0% |
| DESKTOP_SESSION |
gnome |
| XDG_CURRENT_DESKTOP |
GNOME |
| XDG_SESSION_DESKTOP |
gnome |
| XDG_SESSION_TYPE |
wayland |
Type: Performance Issue
Behaviour
Every test run started from the Test Explorer / gutter "run" button takes about 5 seconds longer than the pytest subprocess itself needs. The Testing view's spinner keeps spinning for that extra ~5s after the actual test run has already finished, before the run can be started again.
With the Python extension's log level set to
Trace, thePythonoutput channel shows the same pattern on every single run (not intermittently):The pytest subprocess exits at
.037, and exactly 5000ms later (.039)awaitDeferredWithTimeoutgives up and the run is finally marked finished. This 5000ms gap is identical on every run.Looking at the bundled extension source (
out/client/extension.js), the pytest execution adapter always does, in afinallyblock after the run:where
RESULT_PIPE_DRAIN_TIMEOUT_MS = 5000is hardcoded (no user-facing setting), and:The
deferredis only resolved from inside the results named-pipe wrapper's owndispose()callback (startRunResultNamedPipe, same file), which is expected to fire when the pipe reports a clean end-of-stream/drain. In this environment that resolution never arrives before the 5s timeout, so every run falls through to the "give up and continue" branch and eats the full 5 seconds on top of the real test time.On the Python side (
python_files/vscode_pytest/__init__.py), the writer end of the results pipe is only closed via:i.e. it relies on full interpreter shutdown to close the pipe, rather than closing/flushing the connection proactively right after the last result is written. This looks like the likely reason the "drain" signal the extension is waiting on doesn't arrive in time, making the 5s timeout the common case rather than a rare fallback.
For a fast test suite (a few seconds or less), this hardcoded wait dominates the total run time and makes iterating on individual tests via the Test Explorer noticeably slower than running
pytestdirectly from a terminal.Steps to reproduce:
python.testing.pytestEnabled: trueand at least one pytest test.Trace(Command Palette →Developer: Set Log Level...→Python).Pythonoutput channel: the spinner keeps spinning for ~5s after "Test run finished, subprocess closed." is logged, untilawaitDeferredWithTimeoutgives up.Diagnostic data
Output for
Pythonin theOutputpanel (View→Output, change the drop-down the upper-right of theOutputpanel toPython)Environment
.venv)Extension version: 2026.5.2026070801
VS Code version: Code 1.130.0 (1b6a188127eeaf9194f945eb6eb89a657e93c54c, 2026-07-22T14:55:04Z)
OS version: Linux x64 6.12.96+deb13-amd64
Modes:
python.languageServersetting: NoneUser Settings
Installed Extensions
System Info
GPU0: VENDOR= 0x8086 [Google Inc. (Intel)], DEVICE=0x9b41 [ANGLE (Intel, Mesa Intel(R) UHD Graphics (CML GT2), OpenGL ES 3.2 Mesa 25.0.7-2+deb13u1)], DRIVER_VENDOR=Mesa, DRIVER_VERSION=25.0.7 ACTIVE
Machine model name:
Machine model version:
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
skia_graphite: disabled_off
trees_in_viz: disabled_off
video_decode: enabled
video_encode: disabled_software
vulkan: disabled_off
webgl: enabled
webgpu: enabled
webgpu_on_vk_via_gl_interop: disabled_off
webnn: disabled_off