[Bugfix][CI] Report subprocess test skips as skips, not passes (#58701)
Signed-off-by: Stefan Koncarevic <Stefan.Koncarevic@amd.com> Co-authored-by: Andreas Karatzas <akaratza@amd.com>
This commit is contained in:
co-authored by
Andreas Karatzas
parent
2bc902eb0f
commit
2d7dd0e5c1
+12
-8
@@ -1928,7 +1928,7 @@ def spawn_new_process_for_each_test(f: Callable[_P, None]) -> Callable[_P, None]
|
||||
|
||||
The child inherits the parent's stdout/stderr so its output (engine
|
||||
cores, NCCL, CUDA, ...) reaches the test runner live; the Python-level
|
||||
traceback is serialized to ``tb_file`` for structured re-raising. A
|
||||
traceback or skip reason is serialized to ``tb_file`` for propagation. A
|
||||
native crash leaves ``tb_file`` empty — the diagnostic is then only in
|
||||
the inherited subprocess output.
|
||||
"""
|
||||
@@ -1953,7 +1953,7 @@ def spawn_new_process_for_each_test(f: Callable[_P, None]) -> Callable[_P, None]
|
||||
)
|
||||
|
||||
child_script = (
|
||||
"import sys, importlib, cloudpickle, traceback\n"
|
||||
"import sys, importlib, cloudpickle, traceback, json\n"
|
||||
"try:\n"
|
||||
" from _pytest.outcomes import Skipped\n"
|
||||
"except ImportError:\n"
|
||||
@@ -1965,7 +1965,9 @@ def spawn_new_process_for_each_test(f: Callable[_P, None]) -> Callable[_P, None]
|
||||
" target = getattr(target, name)\n"
|
||||
"try:\n"
|
||||
" target(*data['args'], **data['kwargs'])\n"
|
||||
"except Skipped:\n"
|
||||
"except Skipped as exc:\n"
|
||||
" with open(data['tb_file'], 'w') as fp:\n"
|
||||
" json.dump(str(exc), fp)\n"
|
||||
" sys.exit(0)\n"
|
||||
"except BaseException:\n"
|
||||
" with open(data['tb_file'], 'w') as fp:\n"
|
||||
@@ -1984,18 +1986,20 @@ def spawn_new_process_for_each_test(f: Callable[_P, None]) -> Callable[_P, None]
|
||||
env=env,
|
||||
)
|
||||
|
||||
try:
|
||||
with open(tb_file) as fp:
|
||||
tb = fp.read()
|
||||
except OSError:
|
||||
tb = ""
|
||||
if result.returncode != 0:
|
||||
try:
|
||||
with open(tb_file) as fp:
|
||||
tb = fp.read()
|
||||
except OSError:
|
||||
tb = ""
|
||||
if not tb:
|
||||
tb = "<no Python traceback; see subprocess output above>"
|
||||
raise RuntimeError(
|
||||
f"Test subprocess '{f.__name__}' failed "
|
||||
f"({_format_subprocess_exit(result.returncode)}):\n{tb}"
|
||||
)
|
||||
if tb:
|
||||
pytest.skip(json.loads(tb))
|
||||
finally:
|
||||
with contextlib.suppress(OSError):
|
||||
os.remove(tb_file)
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Tests for spawn_new_process_for_each_test decorator."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.utils import spawn_new_process_for_each_test
|
||||
|
||||
pytest_plugins = ["pytester"]
|
||||
|
||||
|
||||
@spawn_new_process_for_each_test
|
||||
def test_spawn_decorator_passing():
|
||||
@@ -26,6 +30,15 @@ def test_spawn_decorator_skip():
|
||||
pytest.skip("intentional skip")
|
||||
|
||||
|
||||
def test_spawn_decorator_reports_skip(pytester):
|
||||
"""A child skip must remain a skip in the parent pytest report."""
|
||||
result = pytester.runpytest_subprocess(
|
||||
f"{Path(__file__).resolve()}::test_spawn_decorator_skip", "-rs"
|
||||
)
|
||||
result.assert_outcomes(skipped=1)
|
||||
result.stdout.fnmatch_lines(["SKIPPED *intentional skip"])
|
||||
|
||||
|
||||
@spawn_new_process_for_each_test
|
||||
@pytest.mark.parametrize("x,y,expected", [(1, 2, 3), (0, 0, 0)])
|
||||
def test_spawn_decorator_parametrized(x, y, expected):
|
||||
|
||||
Reference in New Issue
Block a user