diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 36607e5..49a114e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,9 @@ Changelog Unreleased ---------- +* Avoid crashing when test node IDs contain surrogate characters from undecodable filesystem names. + In that situation, pytest’s independent cache serialization limitation still requires ``-p no:cacheprovider``. + * Drop Python 3.10 support. 5.0.0 (2026-09-01) diff --git a/src/pytest_randomly/__init__.py b/src/pytest_randomly/__init__.py index f9f724a..9801861 100644 --- a/src/pytest_randomly/__init__.py +++ b/src/pytest_randomly/__init__.py @@ -287,7 +287,7 @@ def reduce_list_of_lists(lists: list[list[T]]) -> list[T]: @lru_cache def _crc32(string: str) -> int: - return crc32(string.encode()) + return crc32(string.encode(errors="surrogatepass")) if have_faker: # pragma: no branch diff --git a/tests/test_pytest_randomly.py b/tests/test_pytest_randomly.py index b9b142e..4334e76 100644 --- a/tests/test_pytest_randomly.py +++ b/tests/test_pytest_randomly.py @@ -1,6 +1,7 @@ from __future__ import annotations import shutil +import sys from unittest import mock import pytest @@ -884,3 +885,16 @@ def test_xdist(n, ourtester): # Can't make any assertion on the order, since output comes back from # workers non-deterministically + + +@pytest.mark.skipif( + sys.platform == "win32", reason="Requires byte-based filesystem names" +) +def test_undecodable_filename(ourtester): + path = ourtester.path / "test_\udcff.py" + path.write_text("def test_one():\n assert True\n", encoding="utf-8") + + # The cache provider independently cannot persist surrogate-containing node IDs. + result = ourtester.runpytest("-p", "no:cacheprovider", "--randomly-seed=1") + + result.assert_outcomes(passed=1)