Skip to content

Refactor cudf-polars test suite onto pytest fixtures - #22212

Merged
rapids-bot[bot] merged 16 commits into
NVIDIA:mainfrom
madsbk:refactor-tests
Apr 27, 2026
Merged

Refactor cudf-polars test suite onto pytest fixtures#22212
rapids-bot[bot] merged 16 commits into
NVIDIA:mainfrom
madsbk:refactor-tests

Conversation

@madsbk

@madsbk madsbk commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Replaces module-level test configuration (DEFAULT_*) with per-test pytest fixtures, and removes the --blocksize-mode CLI option.

Note: The diff is largely mechanical fixture refactoring. The meaningful review surface is limited to:

  • tests/conftest.py
  • cudf_polars/testing/asserts.py
  • CI scripts

Motivation

The test suite currently relies on custom pytest CLI flags (--executor, --cluster, --runtime, --blocksize-mode) that are parsed into module-level globals. Covering multiple configurations requires running pytest multiple times in CI with different flag combinations.

This does not scale with the new frontend model (SPMDEngine, RayEngine, DaskEngine). CLI flags can only express a single configuration per run, and module-level globals make per-test resource setup and teardown awkward (e.g. communicator, RMM, thread pool). Each new engine also expands the CI matrix.

Pytest fixtures map naturally to this. Engines become fixtures with proper lifecycle and scoping, and tests can parametrize over available engines. This removes global state, collapses CI to a single pytest run, and makes it easy to add new engines without touching CI or test configuration.

@madsbk madsbk self-assigned this Apr 20, 2026
@madsbk madsbk added improvement Improvement / enhancement to an existing function non-breaking Non-breaking change labels Apr 20, 2026
@github-actions github-actions Bot added Python Affects Python cuDF API. cudf-polars Issues specific to cudf-polars labels Apr 20, 2026
@GPUtester GPUtester moved this to In Progress in cuDF Python Apr 20, 2026
@madsbk
madsbk force-pushed the refactor-tests branch 2 times, most recently from 5e26c86 to 5f9913e Compare April 20, 2026 14:40
@madsbk madsbk removed this from cuDF Python Apr 20, 2026
@madsbk
madsbk force-pushed the refactor-tests branch 5 times, most recently from 1a38c35 to a464a61 Compare April 21, 2026 13:41
@madsbk madsbk changed the title [cudf-polar] Introduce engine pytest fixture Refactor cudf-polars test suite onto pytest fixtures Apr 21, 2026
@madsbk
madsbk force-pushed the refactor-tests branch 3 times, most recently from 14fbfb3 to 15e9f36 Compare April 22, 2026 06:06
Replaces module-level test configuration (`DEFAULT_EXECUTOR`, `DEFAULT_RUNTIME`, `DEFAULT_CLUSTER`, `DEFAULT_BLOCKSIZE_MODE`) with per-test pytest fixtures, and removes the `--blocksize-mode` CLI option.

**Note:** The diff is largely mechanical fixture refactoring. The meaningful review surface is limited to:

* `tests/conftest.py`
* `cudf_polars/testing/asserts.py`
* CI scripts
@madsbk
madsbk marked this pull request as ready for review April 23, 2026 13:04
@madsbk
madsbk requested review from a team as code owners April 23, 2026 13:04
@NVIDIA NVIDIA deleted a comment from copy-pr-bot Bot Apr 23, 2026

@gforsyth gforsyth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small changes requested in the logging in the CI scripts

Comment thread ci/run_cudf_polars_experimental_pytests.sh Outdated
Comment thread ci/run_cudf_polars_experimental_pytests.sh

@mroeschke mroeschke left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some optional suggestions and a question.

Also agreed with #22212 (comment)

Comment thread ci/run_cudf_polars_pytests.sh
Comment thread python/cudf_polars/tests/conftest.py
Comment on lines +149 to +154
_ENGINE_PARAMS = ["in-memory"]
if importlib.util.find_spec("rapidsmpf") is not None:
_ENGINE_PARAMS.append("spmd")


@pytest.fixture(params=_ENGINE_PARAMS)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_ENGINE_PARAMS = ["in-memory"]
if importlib.util.find_spec("rapidsmpf") is not None:
_ENGINE_PARAMS.append("spmd")
@pytest.fixture(params=_ENGINE_PARAMS)
@pytest.fixture(params=["in-memory", pytest.param("spmd", marks=pytest.mark.skipif(importlib.util.find_spec("rapidsmpf") is not None, reason="rapidsmpf not installed")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s defer this until rapidsmpf is always available in CI. Right now, this would produce a lot of extra skipped: rapidsmpf not installed lines per run.

--runtime rapidsmpf \
--blocksize-mode small
echo "Running tests"
timeout 10m python -m pytest --cache-clear "$@" tests --ignore=tests/experimental/legacy

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How close are we to collapsing these two pytest calls into ci/run_cudf_polars_pytests.sh?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose a final state of these existing runs should be

  1. With the in-memory executor
  2. With the streaming executor, single cluster with rapidsmpf
  3. With the streaming executor, distributed dask cluster with rapidsmpf

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully we can remove all the legacy code next week.

At that point, we’ll be left with the in-memory engine alongside RayEngine, DaskEngine, and SPMDEngine.

@madsbk
madsbk requested review from mroeschke and wence- April 24, 2026 13:57

@TomAugspurger TomAugspurger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update CI scripts and conftest files look good.

return cudf_polars.testing.asserts.DEFAULT_RUNTIME == "rapidsmpf"
def using_streaming_engine(engine: pl.GPUEngine) -> bool:
"""True when the active ``engine`` fixture is an :class:`StreamingEngine`."""
try:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this try/except is unavoidable for now, but once it's the default and we depend on rapidsmpf I'd be more comfortable if this errors loudly if there's an import issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

@pentschev pentschev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo suggestion and a couple of comments. LGTM.

Comment thread python/cudf_polars/tests/conftest.py Outdated
Comment on lines +75 to +80
"""Session-scoped communicator — bootstrapped once and shared across all tests.

Sharing a single communicator avoids the file-based bootstrap race that can
cause hangs when ``create_ucxx_comm()`` is called repeatedly in the same
``rrun`` session (stale barrier files / stale ``ucxx_root_address`` KV entry).
"""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine here, but I wonder if we should change something in rrun or there's nothing we should do there. We will probably be bitten by the same type of issue in every new pytest job that includes rrun. One thing that could be done differently (although that's also on the client/user side) would be to add a barrier at the end of each test, probably not worth the extra cost here though. On rrun's side I can't immediately think of a solution to that, perhaps it would need some care on permitting proper destruction/respawning of the worker being used, this is definitely something that wasn't prioritized.

Comment on lines +239 to +247
# Ray's internal subprocess management leaks `/dev/null` file handles, and
# distributed's shutdown leaves unclosed sockets. Under Python 3.14 +
# pytest 9, these surface as unraisable `ResourceWarning`s and — combined
# with `filterwarnings = ["error", ...]` in pyproject.toml — fail
# otherwise-unrelated tests when the GC finalizer happens to fire during
# them. With `pytest-xdist --dist=worksteal`, the leak can land in any
# test that shares a worker with a ray/dask test, so the suppression must
# apply globally rather than per-module.
config.addinivalue_line("filterwarnings", "ignore::ResourceWarning")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only downside of this is that any legit non-Ray/non-Distributed leaks will be swallowed too.

@madsbk

madsbk commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

/merge

1 similar comment
@madsbk

madsbk commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit edc4876 into NVIDIA:main Apr 27, 2026
136 of 137 checks passed
@madsbk
madsbk deleted the refactor-tests branch April 27, 2026 10:18
vyasr pushed a commit to vyasr/cudf that referenced this pull request May 4, 2026
Replaces module-level test configuration (`DEFAULT_*`) with per-test pytest fixtures, and removes the `--blocksize-mode` CLI option.

**Note:** The diff is largely mechanical fixture refactoring. The meaningful review surface is limited to:

* `tests/conftest.py`
* `cudf_polars/testing/asserts.py`
* CI scripts

---

### Motivation

The test suite currently relies on custom pytest CLI flags (`--executor`, `--cluster`, `--runtime`, `--blocksize-mode`) that are parsed into module-level globals. Covering multiple configurations requires running pytest multiple times in CI with different flag combinations.

This does not scale with the new frontend model (`SPMDEngine`, `RayEngine`, `DaskEngine`). CLI flags can only express a single configuration per run, and module-level globals make per-test resource setup and teardown awkward (e.g. communicator, RMM, thread pool). Each new engine also expands the CI matrix.

Pytest fixtures map naturally to this. Engines become fixtures with proper lifecycle and scoping, and tests can parametrize over available engines. This removes global state, collapses CI to a single pytest run, and makes it easy to add new engines without touching CI or test configuration.

Authors:
  - Mads R. B. Kristensen (https://github.com/madsbk)
  - Peter Andreas Entschev (https://github.com/pentschev)

Approvers:
  - Gil Forsyth (https://github.com/gforsyth)
  - Tom Augspurger (https://github.com/TomAugspurger)
  - Peter Andreas Entschev (https://github.com/pentschev)
  - Lawrence Mitchell (https://github.com/wence-)

URL: NVIDIA#22212
rapids-bot Bot pushed a commit that referenced this pull request May 7, 2026
…#22281)

closes #21466
closes #21767

Waiting for #22212

* Makes rapidsmpf a required dependency of cudf_polars
* Removes the following `StreamingExecutor` options as they were "experimental" with associated code paths
    * `StreamingExecutor.runtime`
    * `StreamingExecutor.shuffle_method`
    * `StreamingExecutor.unique_fraction`
    * `StreamingExecutor.groupby_n_ary`
    * `StreamingExecutor.rapidsmpf_spill`
* Removes the task runtime and associated tests
* Some tests we modified to only test 1 specific test configuration because of #22346 to pass these tests for now. Planning on revisiting this once rapidsmpf becomes the default

Ops-Bot-Merge-Barrier: true

Authors:
  - Matthew Roeschke (https://github.com/mroeschke)

Approvers:
  - Mads R. B. Kristensen (https://github.com/madsbk)
  - Bradley Dice (https://github.com/bdice)
  - Matthew Murray (https://github.com/Matt711)
  - Lawrence Mitchell (https://github.com/wence-)

URL: #22281
galipremsagar pushed a commit to galipremsagar/cudf that referenced this pull request May 8, 2026
…NVIDIA#22281)

closes NVIDIA#21466
closes NVIDIA#21767

Waiting for NVIDIA#22212

* Makes rapidsmpf a required dependency of cudf_polars
* Removes the following `StreamingExecutor` options as they were "experimental" with associated code paths
    * `StreamingExecutor.runtime`
    * `StreamingExecutor.shuffle_method`
    * `StreamingExecutor.unique_fraction`
    * `StreamingExecutor.groupby_n_ary`
    * `StreamingExecutor.rapidsmpf_spill`
* Removes the task runtime and associated tests
* Some tests we modified to only test 1 specific test configuration because of NVIDIA#22346 to pass these tests for now. Planning on revisiting this once rapidsmpf becomes the default

Ops-Bot-Merge-Barrier: true

Authors:
  - Matthew Roeschke (https://github.com/mroeschke)

Approvers:
  - Mads R. B. Kristensen (https://github.com/madsbk)
  - Bradley Dice (https://github.com/bdice)
  - Matthew Murray (https://github.com/Matt711)
  - Lawrence Mitchell (https://github.com/wence-)

URL: NVIDIA#22281
shrshi pushed a commit to shrshi/cudf that referenced this pull request May 12, 2026
Replaces module-level test configuration (`DEFAULT_*`) with per-test pytest fixtures, and removes the `--blocksize-mode` CLI option.

**Note:** The diff is largely mechanical fixture refactoring. The meaningful review surface is limited to:

* `tests/conftest.py`
* `cudf_polars/testing/asserts.py`
* CI scripts

---

### Motivation

The test suite currently relies on custom pytest CLI flags (`--executor`, `--cluster`, `--runtime`, `--blocksize-mode`) that are parsed into module-level globals. Covering multiple configurations requires running pytest multiple times in CI with different flag combinations.

This does not scale with the new frontend model (`SPMDEngine`, `RayEngine`, `DaskEngine`). CLI flags can only express a single configuration per run, and module-level globals make per-test resource setup and teardown awkward (e.g. communicator, RMM, thread pool). Each new engine also expands the CI matrix.

Pytest fixtures map naturally to this. Engines become fixtures with proper lifecycle and scoping, and tests can parametrize over available engines. This removes global state, collapses CI to a single pytest run, and makes it easy to add new engines without touching CI or test configuration.

Authors:
  - Mads R. B. Kristensen (https://github.com/madsbk)
  - Peter Andreas Entschev (https://github.com/pentschev)

Approvers:
  - Gil Forsyth (https://github.com/gforsyth)
  - Tom Augspurger (https://github.com/TomAugspurger)
  - Peter Andreas Entschev (https://github.com/pentschev)
  - Lawrence Mitchell (https://github.com/wence-)

URL: NVIDIA#22212
shrshi pushed a commit to shrshi/cudf that referenced this pull request May 12, 2026
…NVIDIA#22281)

closes NVIDIA#21466
closes NVIDIA#21767

Waiting for NVIDIA#22212

* Makes rapidsmpf a required dependency of cudf_polars
* Removes the following `StreamingExecutor` options as they were "experimental" with associated code paths
    * `StreamingExecutor.runtime`
    * `StreamingExecutor.shuffle_method`
    * `StreamingExecutor.unique_fraction`
    * `StreamingExecutor.groupby_n_ary`
    * `StreamingExecutor.rapidsmpf_spill`
* Removes the task runtime and associated tests
* Some tests we modified to only test 1 specific test configuration because of NVIDIA#22346 to pass these tests for now. Planning on revisiting this once rapidsmpf becomes the default

Ops-Bot-Merge-Barrier: true

Authors:
  - Matthew Roeschke (https://github.com/mroeschke)

Approvers:
  - Mads R. B. Kristensen (https://github.com/madsbk)
  - Bradley Dice (https://github.com/bdice)
  - Matthew Murray (https://github.com/Matt711)
  - Lawrence Mitchell (https://github.com/wence-)

URL: NVIDIA#22281
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cudf-polars Issues specific to cudf-polars improvement Improvement / enhancement to an existing function non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants