Skip to content

[Tests] Add xet/no_xet pytest markers to filter Xet vs non-Xet tests#4336

Merged
Wauplin merged 4 commits into
mainfrom
xet-test-markers
Jun 10, 2026
Merged

[Tests] Add xet/no_xet pytest markers to filter Xet vs non-Xet tests#4336
Wauplin merged 4 commits into
mainfrom
xet-test-markers

Conversation

@Wauplin

@Wauplin Wauplin commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Until now, deciding which tests run with/without hf_xet relied on two mechanisms that were rarely in sync: name-based CI filtering (pytest -k 'test_xet or test_buckets or test_copy_files') and @requires("hf_xet") decorators. In the end it was hard to know if a test ran at all, and local runs (hf_xet installed) differed from CI. This PR replaces both with explicit markers enforced by a single autouse fixture (xet_mode in tests/conftest.py):

  • @pytest.mark.xet → test requires hf_xet: skipped if not installed, Xet force-enabled otherwise. Whole modules are marked via pytestmark = pytest.mark.xet (xet upload/download/utils, buckets, copy_files).
  • @pytest.mark.no_xet → test must run without hf_xet: skipped if hf_xet is installed. No reliance on HF_HUB_DISABLE_XET — the test only runs in environments where hf_xet is genuinely absent.
  • unmarked → test must work regardless of Xet: nothing forced.

CI mapping (ubuntu + windows):

  • "Xet only" job (hf_xet installed): -m 'not no_xet'xet tests + all unmarked tests, with Xet.
  • all other jobs (hf_xet uninstalled): -m 'not xet'no_xet tests + all unmarked tests, without Xet.

So unmarked tests now run twice in CI (once per mode) — that's what actually verifies "works regardless of Xet" instead of just documenting it. Inference tests stay excluded from the Xet job (they have their own job and don't depend on Xet). Marking a test with both markers is a hard failure, and --strict-markers is enabled so a typo'd marker is a collection error.

$ pytest tests -m xet           # 269 tests  (xet-required)
$ pytest tests -m "not xet"     # 2192 tests (what CI runs without hf_xet)
$ pytest tests -m "not no_xet"  # 2461 tests (what CI runs with hf_xet)

Decisions taken

  • Unmarked tests run in both CI jobs (rather than only the non-xet job, or only on one matrix entry). Costs more runner minutes on the "Xet only" job (~270 → ~2400 tests) but wall-clock is similar (parallel jobs) and it's the only option where a hidden Xet-dependence in an unmarked test surfaces in CI.
  • no_xet tests are skipped when hf_xet is installed, rather than force-disabling Xet via HF_HUB_DISABLE_XET. Symmetric with xet (each marker pins the test to one environment) and doesn't depend on the env-var escape hatch behaving correctly everywhere. Locally (hf_xet installed) no_xet tests skip; CI covers them in the non-xet jobs.
  • no_xet currently has zero uses: I couldn't statically identify tests that break with Xet enabled. The first "Xet only" runs are the discovery mechanism — each failure there is either a missing no_xet mark or a real Xet-path bug. Expect some triage on this PR's CI.
  • The hf_xet uninstall step in non-Xet jobs is kept: it's what guarantees unmarked tests run Xet-free there, and catches accidental hard imports of hf_xet.

Bugs the old -k filtering was hiding

  • TestSkillsMarketplaceCLI (tests/test_cli.py) was @requires("hf_xet") but matched no -k pattern → it never ran in any CI job (only collected where hf_xet was uninstalled → always skipped). Now marked xet and running.
  • test_xet_callback_sums_increments_across_concurrent_commits (tests/test_upload_pipeline.py, fully mocked, no hf_xet needed) was routed to the Xet job purely by its name.
  • The Windows Xet job only ran -k "test_xet" → buckets/copy_files tests never ran on Windows at all.

Sanity check of the fixture (with hf_xet installed locally):

def test_unmarked_uses_environment():
    assert is_xet_available()       # passed

@pytest.mark.no_xet
def test_no_xet_skipped_when_installed():
    raise AssertionError(...)       # SKIPPED: "Test must run without `hf_xet` installed"

@pytest.mark.xet
def test_xet_forced_on():
    assert is_xet_available()       # passed

🤖 Generated with Claude Code


Note

Low Risk
Test and CI infrastructure only; no production library behavior changes. CI may surface previously skipped or mis-routed tests when the expanded Xet job runs more suites.

Overview
Replaces ad-hoc Xet test selection (pytest -k name patterns and @requires("hf_xet")) with xet / no_xet pytest markers and an autouse xet_mode fixture in tests/conftest.py that skips or force-enables Xet consistently.

CI renames matrix jobs to no hf_xet / with hf_xet, uninstalls hf_xet outside the Xet job, and selects tests with -m 'not xet' vs -m 'not no_xet' (inference still excluded from the Xet job). The Windows Xet job now runs the same marker set as Ubuntu instead of only -k test_xet.

Config & docs: pyproject.toml registers markers and --strict-markers; CONTRIBUTING.md documents the three modes and example pytest -m commands.

Tests: Xet-dependent modules use pytestmark = pytest.mark.xet (buckets, copy_files, xet upload/download/utils, one CLI class); per-test @requires("hf_xet") decorators are removed.

Reviewed by Cursor Bugbot for commit 58ea86e. Bugbot is set up for automated code reviews on this repo. Configure here.

Replace the name-based CI filtering (pytest -k 'test_xet or test_buckets
or test_copy_files') and ad-hoc @requires("hf_xet") decorators with
explicit pytest markers enforced by an autouse fixture:

- @pytest.mark.xet: test requires hf_xet => skipped if not installed,
  Xet force-enabled otherwise.
- @pytest.mark.no_xet: test must run without Xet => Xet force-disabled
  via HF_HUB_DISABLE_XET, even if hf_xet is installed.
- unmarked: test must work regardless of Xet => nothing forced; CI runs
  unmarked tests both with hf_xet ("Xet only" job, -m 'not no_xet') and
  without (other jobs, -m 'not xet').

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread tests/conftest.py Outdated
Don't rely on HF_HUB_DISABLE_XET to force-disable Xet for no_xet tests:
skip them instead when hf_xet is installed. They run in the CI jobs
where hf_xet is uninstalled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bot-ci-comment

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Comment thread .github/workflows/python-tests.yml
…no hf_xet"

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0a8b1c3. Configure here.

Comment thread tests/conftest.py
@Wauplin Wauplin requested a review from hanouticelina June 10, 2026 14:37
@Wauplin Wauplin marked this pull request as ready for review June 10, 2026 14:37
@Wauplin

Wauplin commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Not a hurry but I'd like to have this PR merged to use it in #4336 (currently CI is failing but this PR should make it easy to fix it)

@hanouticelina hanouticelina left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

makes sense!

@Wauplin Wauplin merged commit 92009d4 into main Jun 10, 2026
23 of 26 checks passed
@Wauplin Wauplin deleted the xet-test-markers branch June 10, 2026 16:30
Wauplin added a commit that referenced this pull request Jun 11, 2026
* [Tests] Add `inference` pytest marker to filter inference tests

Replace the name-based CI filtering (pytest -k 'test_inference' / -k 'not
test_inference') with an explicit `pytest.mark.inference` marker, mirroring the
xet/no_xet markers introduced in #4336.

The six `test_inference_*.py` modules are tagged with
`pytestmark = pytest.mark.inference`. CI now selects them with `-m inference`
(the "Inference only" job) and excludes them elsewhere with `-m 'not inference'`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [Tests] Drop endpoints from inference marker + remove redundant comments

test_inference_endpoints.py is mocked InferenceEndpoint logic, not an inference
test => unmark it so it runs in the regular jobs. Also drop the now-redundant
explanatory comments above each `pytestmark`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@huggingface-hub-bot

Copy link
Copy Markdown
Contributor

This PR has been shipped as part of the v1.19.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants