-
Notifications
You must be signed in to change notification settings - Fork 20
[CI] Add slow marker and remove un-necessary tests #711
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hughperkins
wants to merge
15
commits into
main
Choose a base branch
from
hp/mark-slow-tests-only
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
be56109
Skip the slowest tests by default
f58248a
Trim n parametrize lists to {smallest, 12}
a2f4f91
[Demo] cholesky_blocked: take N / N_ENVS / WARMUP / ITERS via argparse
eae1a36
[Test] test_tile16_cholesky_blocked_demo: invoke demo in smoke-mode
dc1319e
[Test] test_matmul_chain_qipc_sizes: parametrize on matrix shapes
81d45a0
[Test] test_gdar_mpm: parametrize on particles_side / n_grid / num_steps
1b08117
[Test] test_device_{reduce,exclusive_scan}: fuse {add,min,max} into o…
8acaaec
[Style] black: reformat test_tile16_cholesky_blocked_demo cmd list + …
e57752a
[Test] test_subgroup_full_matches_tiled: fuse 20 thin subgroup-op wra…
4c18c86
[Test] test_block_reduce{,_all}: fuse {add,min,max} into op-parametri…
5fb930e
[Test] test_block_inclusive: fuse {add,min,max} into one op-parametri…
aa25a36
[Test] test_block_exclusive_minmax: fuse {min,max} into one op-parame…
11b3a89
[Style] Reflow CI-flagged 80c-wrapped comments to 120c
7389b5f
[Doc] contributing.md: shorten testing bullet per PR review
a85c6ec
[Doc] unit_testing: add slow-only test-suite guide
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,6 +82,7 @@ init_options | |
| :maxdepth: 1 | ||
| :titlesonly: | ||
|
|
||
| unit_testing | ||
| kernel_coverage | ||
| ``` | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| # Unit testing | ||
|
|
||
| This page documents how to run, write, and tune the Quadrants Python unit test suite. For setup of the build / dev environment, see [contributing.md](contributing.md). | ||
|
|
||
| ## Running the tests | ||
|
|
||
| The test suite is run via the project's launcher, **not** by invoking `pytest` directly: | ||
|
|
||
| ``` | ||
| python tests/run_tests.py | ||
| ``` | ||
|
|
||
| The launcher sets up the test-only env vars (kernel offline cache, watchdog, xdist worker count, etc.) and forwards any unrecognised flags to pytest. Calling `pytest` directly skips that setup and behaves differently. | ||
|
|
||
| Common one-liners: | ||
|
|
||
| ``` | ||
| # run one file | ||
| python tests/run_tests.py test_tile16 | ||
|
|
||
| # run one test (any pytest -k expression) | ||
| python tests/run_tests.py -k test_tile16_cholesky | ||
|
|
||
| # run on a specific backend (or comma-separated list) | ||
| python tests/run_tests.py --arch cuda | ||
| python tests/run_tests.py --arch metal -k tile16 | ||
|
|
||
| # same, via env var (handy for CI) | ||
| QD_WANTED_ARCHS=metal,vulkan python tests/run_tests.py | ||
|
|
||
| # rerun the last failing tests first | ||
| python tests/run_tests.py -f | ||
|
|
||
| # stop at the first failure | ||
| python tests/run_tests.py -x | ||
| ``` | ||
|
|
||
| The target architecture can also be set via `QD_WANTED_ARCHS` (comma-separated; supports `^arch` to exclude rather than include). | ||
|
|
||
| ## Markers | ||
|
|
||
| ### `@pytest.mark.slow` | ||
|
|
||
| Marks a test as **slow**. `tests/run_tests.py` adds `-m "not slow"` to the pytest invocation by default; pass `--run-slow` to opt back in: | ||
|
|
||
| ``` | ||
| # default: skip slow | ||
| python tests/run_tests.py | ||
|
|
||
| # include slow | ||
| python tests/run_tests.py --run-slow | ||
|
|
||
| # slow ONLY (e.g. nightly job) | ||
| python tests/run_tests.py -m slow --run-slow | ||
| ``` | ||
|
|
||
| The marker is used in two patterns: | ||
|
|
||
| 1. **Whole-test slow**: the whole test takes a long time. | ||
|
|
||
| ```python | ||
| @pytest.mark.slow | ||
| def test_thing_that_is_always_slow(): | ||
| ... | ||
| ``` | ||
|
|
||
| 2. **Slow-marked parametrize case**: | ||
|
|
||
| ```python | ||
| @pytest.mark.parametrize("n", [4, pytest.param(12, marks=pytest.mark.slow)]) | ||
| def test_sym_eig_general(n): | ||
| ... | ||
| ``` | ||
|
|
||
| In this specific example the default suite still exercises the code path; the slow lane just adds the larger-size variant for full coverage. | ||
|
|
||
| ## Writing new tests | ||
|
|
||
| The standard recipe combines `@test_utils.test(...)` (arch / option matrix) with `@pytest.mark.parametrize`: | ||
|
|
||
| ```python | ||
| import pytest | ||
| import quadrants as qd | ||
| from tests import test_utils | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("n", [4, pytest.param(12, marks=pytest.mark.slow)]) | ||
| @test_utils.test(arch=qd.gpu, default_fp=qd.f32) | ||
| def test_my_thing(n): | ||
| ... | ||
| ``` | ||
|
|
||
| `@test_utils.test` is what wires the test into the per-backend matrix and applies platform exclusions (`exclude=`), extension requirements (`require=`, e.g. `qd.extension.data64` for f64 tests), and per-test options (`default_fp`, `fast_math`, etc.). See `tests/test_utils.py` for the full surface. | ||
|
|
||
| Common helpers in `tests/test_utils.py`: | ||
|
|
||
| - `test_utils.skip_if_f64_unsupported(dtype)` — skip the current test at runtime if `dtype == qd.f64` and the active backend can't carry f64 through buffer I/O (Metal, MoltenVK on Darwin). Use inside a parametrized test that sweeps both f32 and f64. | ||
| - `test_utils.expected_archs()` — list of archs that the current `QD_WANTED_ARCHS` allows. Used to skip tests with no satisfiable arch. | ||
|
|
||
| ## Advanced | ||
|
|
||
| Optional knobs and runtime details. The defaults work for most contributors. | ||
|
|
||
| ### Per-test timeout | ||
|
|
||
| Per-test timeouts default to 600 s and are enforced by `pytest_hardtle`, a CFFI-compiled C watchdog that can kill tests hung in native GPU calls even when the GIL is held. | ||
|
|
||
| ### Kernel compilation cache | ||
|
|
||
| During each test session the kernel compilation cache lives in a fresh, empty temp directory created by pytest's [`tmp_path_factory`](https://docs.pytest.org/en/stable/how-to/tmp_path.html) — typically `/tmp/pytest-of-<user>/pytest-<N>/qdcache0/`. Old session directories are cleaned up automatically by pytest's retention policy. This cache is separate from the user-facing `~/.cache/quadrants/` cache, and avoids recompiling identical kernels after each `qd.reset()` / `qd.init()` cycle within a session. | ||
|
|
||
| ### Per-file timing breakdown | ||
|
|
||
| Set `QD_FILE_TIMING=1` to print a per-file duration summary at the end of the session: | ||
|
|
||
| ``` | ||
| QD_FILE_TIMING=1 python tests/run_tests.py | ||
| ``` | ||
|
|
||
| This is enabled by default in the Mac CI job; the results appear in the GitHub Actions job summary and are the primary tool for identifying slow test files. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wrapped description line is parsed as a second marker entry, so pytest now registers an unintended marker named
pass --run-slow to include them, or directly \pytest -m slow` to run only the slow ones.instead of treating it as part ofslow's description. You can see this inpytest --markers, and it can confuse marker tooling (and future strict marker validation) becausetests/pytest.inino longer defines markers as onename: description` per line.Useful? React with 👍 / 👎.