name: "Run Pytest" description: "Run pytest with appropriate flags for the test type and platform" inputs: test-type: description: "Type of tests to run: unit, integration, client_process, or conformance" required: false default: "unit" runs: using: "composite" steps: - name: Run pytest shell: bash run: | if [ "${{ inputs.test-type }}" == "integration" ]; then MARKER="integration" TIMEOUT="30" MAX_PROCS="2" EXTRA_FLAGS="" elif [ "${{ inputs.test-type }}" == "client_process" ]; then MARKER="client_process or subprocess_heavy" TIMEOUT="5" MAX_PROCS="0" EXTRA_FLAGS="-x" elif [ "${{ inputs.test-type }}" == "conformance" ]; then MARKER="conformance" TIMEOUT="120" MAX_PROCS="0" EXTRA_FLAGS="-x" else MARKER="not integration and not client_process and not subprocess_heavy and not conformance" TIMEOUT="5" MAX_PROCS="4" EXTRA_FLAGS="" fi # Windows previously ran serially: parallel workers crashed intermittently # when many tests spawned stdio subprocesses (#2715, reverted in #2726). # Most of those tests now run in-memory, but tests that spawn a fresh # interpreter importing all of FastMCP still crash xdist workers on the # 2-core Windows runners. They carry the subprocess_heavy marker and run # in the serial client_process step instead. PARALLEL_FLAGS="" if [ "$MAX_PROCS" != "0" ]; then PARALLEL_FLAGS="--numprocesses auto --maxprocesses $MAX_PROCS --dist worksteal" fi # pytest-timeout has no signal-based method on Windows, so it falls back # to the thread method, which dumps stacks and os._exit()s the process. # Under a contended runner that turns a single slow test into a dead # xdist worker, failing whichever unrelated test that worker happened to # be running. Give parallel Windows runs more headroom so ordinary # scheduling jitter does not take a worker down. if [ "$RUNNER_OS" == "Windows" ] && [ "$MAX_PROCS" != "0" ]; then TIMEOUT=$((TIMEOUT * 4)) fi uv run --no-sync pytest \ --inline-snapshot=disable \ --timeout=$TIMEOUT \ --durations=50 \ -m "$MARKER" \ $PARALLEL_FLAGS \ $EXTRA_FLAGS \ tests