Skip to content

Commit e4e2767

Browse files
rwgkcursoragent
andcommitted
test: use subtests in cuda.core system device loops
Keep per-device skips and xfails from aborting the rest of the GPU system coverage. Require pytest 9 in cuda.core test environments so the built-in subtests fixture is available. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 2849053 commit e4e2767

3 files changed

Lines changed: 57 additions & 53 deletions

File tree

cuda_core/pixi.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ cuda-version = ["12.*", "13.2.*"]
1515
[feature.test.dependencies]
1616
cuda-core = { path = "." }
1717
ml_dtypes = "*"
18-
pytest = "*"
18+
pytest = ">=9"
1919
pytest-benchmark = "*"
2020
pytest-randomly = "*"
2121
pytest-repeat = "*"
@@ -99,7 +99,7 @@ numpy = "*"
9999
numpydoc = "*"
100100
pip = "*"
101101
pydata-sphinx-theme = "*"
102-
pytest = "*"
102+
pytest = ">=9"
103103
scipy = "*"
104104
sphinx = "<8.2.0"
105105
sphinx-copybutton = "*"

cuda_core/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ cu12 = ["cuda-bindings[all]==12.*"]
5757
cu13 = ["cuda-bindings[all]==13.*"]
5858

5959
[dependency-groups]
60-
test = ["cython>=3.2,<3.3", "setuptools", "pytest>=6.2.4", "pytest-benchmark", "pytest-randomly", "pytest-repeat", "pytest-rerunfailures", "cloudpickle", "psutil", "cffi"]
60+
test = ["cython>=3.2,<3.3", "setuptools", "pytest>=9", "pytest-benchmark", "pytest-randomly", "pytest-repeat", "pytest-rerunfailures", "cloudpickle", "psutil", "cffi"]
6161
ml-dtypes = ["ml-dtypes>=0.5.4,<0.6.0"]
6262
test-cu12 = [ {include-group = "ml-dtypes" }, {include-group = "test" }, "cupy-cuda12x; python_version < '3.14'", "cuda-toolkit[cudart]==12.*"] # runtime headers needed by CuPy
6363
test-cu13 = [ {include-group = "ml-dtypes" }, {include-group = "test" }, "cupy-cuda13x; python_version < '3.14'", "cuda-toolkit[cudart]==13.*"] # runtime headers needed by CuPy

cuda_core/tests/system/test_system_device.py

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -341,18 +341,19 @@ def test_c2c_mode_enabled():
341341

342342

343343
@pytest.mark.skipif(helpers.IS_WSL or helpers.IS_WINDOWS, reason="Persistence mode not supported on WSL or Windows")
344-
def test_persistence_mode_enabled():
344+
def test_persistence_mode_enabled(subtests):
345345
for device in system.Device.get_all_devices():
346-
is_enabled = device.is_persistence_mode_enabled
347-
assert isinstance(is_enabled, bool)
348-
try:
349-
device.is_persistence_mode_enabled = False
350-
except nvml.NoPermissionError as e:
351-
pytest.xfail(f"nvml.NoPermissionError: {e}")
352-
try:
353-
assert device.is_persistence_mode_enabled is False
354-
finally:
355-
device.is_persistence_mode_enabled = is_enabled
346+
with subtests.test(device_index=device.index):
347+
is_enabled = device.is_persistence_mode_enabled
348+
assert isinstance(is_enabled, bool)
349+
try:
350+
device.is_persistence_mode_enabled = False
351+
except nvml.NoPermissionError as e:
352+
pytest.xfail(f"nvml.NoPermissionError: {e}")
353+
try:
354+
assert device.is_persistence_mode_enabled is False
355+
finally:
356+
device.is_persistence_mode_enabled = is_enabled
356357

357358

358359
def test_field_values():
@@ -615,63 +616,66 @@ def test_clock_event_reasons():
615616
assert all(isinstance(reason, system.ClocksEventReasons) for reason in reasons)
616617

617618

618-
def test_fan():
619+
def test_fan(subtests):
619620
for device in system.Device.get_all_devices():
620621
# The fan APIs are only supported on discrete devices with fans,
621622
# but when they are not available `device.num_fans` returns 0.
622623
if device.num_fans == 0:
623-
pytest.skip("Device has no fans to test")
624+
with subtests.test(device_index=device.index):
625+
pytest.skip("Device has no fans to test")
624626

625627
for fan_idx in range(device.num_fans):
626-
fan_info = device.get_fan(fan_idx)
627-
assert isinstance(fan_info, _device.FanInfo)
628+
with subtests.test(device_index=device.index, fan_idx=fan_idx):
629+
fan_info = device.get_fan(fan_idx)
630+
assert isinstance(fan_info, _device.FanInfo)
628631

629-
speed = fan_info.speed
630-
assert isinstance(speed, int)
631-
assert 0 <= speed <= 200
632-
try:
633-
fan_info.speed = 50
634-
except nvml.NoPermissionError as e:
635-
pytest.xfail(f"nvml.NoPermissionError: {e}")
636-
try:
637-
fan_info.speed = speed
632+
speed = fan_info.speed
633+
assert isinstance(speed, int)
634+
assert 0 <= speed <= 200
635+
try:
636+
fan_info.speed = 50
637+
except nvml.NoPermissionError as e:
638+
pytest.xfail(f"nvml.NoPermissionError: {e}")
639+
try:
640+
fan_info.speed = speed
638641

639-
speed_rpm = fan_info.speed_rpm
640-
assert isinstance(speed_rpm, int)
641-
assert speed_rpm >= 0
642+
speed_rpm = fan_info.speed_rpm
643+
assert isinstance(speed_rpm, int)
644+
assert speed_rpm >= 0
642645

643-
target_speed = fan_info.target_speed
644-
assert isinstance(target_speed, int)
645-
assert speed <= target_speed * 2
646+
target_speed = fan_info.target_speed
647+
assert isinstance(target_speed, int)
648+
assert speed <= target_speed * 2
646649

647-
min_, max_ = fan_info.min_max_speed
648-
assert isinstance(min_, int)
649-
assert isinstance(max_, int)
650-
assert min_ <= max_
650+
min_, max_ = fan_info.min_max_speed
651+
assert isinstance(min_, int)
652+
assert isinstance(max_, int)
653+
assert min_ <= max_
651654

652-
control_policy = fan_info.control_policy
653-
assert isinstance(control_policy, system.FanControlPolicy)
654-
finally:
655-
fan_info.set_default_speed()
655+
control_policy = fan_info.control_policy
656+
assert isinstance(control_policy, system.FanControlPolicy)
657+
finally:
658+
fan_info.set_default_speed()
656659

657660

658-
def test_cooler():
661+
def test_cooler(subtests):
659662
for device in system.Device.get_all_devices():
660-
# The cooler APIs are only supported on discrete devices with fans,
661-
# but when they are not available `device.num_fans` returns 0.
662-
if device.num_fans == 0:
663-
pytest.skip("Device has no coolers to test")
663+
with subtests.test(device_index=device.index):
664+
# The cooler APIs are only supported on discrete devices with fans,
665+
# but when they are not available `device.num_fans` returns 0.
666+
if device.num_fans == 0:
667+
pytest.skip("Device has no coolers to test")
664668

665-
with unsupported_before(device, DeviceArch.MAXWELL):
666-
cooler_info = device.cooler
669+
with unsupported_before(device, DeviceArch.MAXWELL):
670+
cooler_info = device.cooler
667671

668-
assert isinstance(cooler_info, _device.CoolerInfo)
672+
assert isinstance(cooler_info, _device.CoolerInfo)
669673

670-
signal_type = cooler_info.signal_type
671-
assert isinstance(signal_type, system.CoolerControl)
674+
signal_type = cooler_info.signal_type
675+
assert isinstance(signal_type, system.CoolerControl)
672676

673-
target = cooler_info.target
674-
assert all(isinstance(t, system.CoolerTarget) for t in target)
677+
target = cooler_info.target
678+
assert all(isinstance(t, system.CoolerTarget) for t in target)
675679

676680

677681
def test_temperature():

0 commit comments

Comments
 (0)