HugBucket uses pytest with asyncio_mode = "auto" configured in pyproject.toml. This means all async def test functions run automatically in an event loop — no @pytest.mark.asyncio decorator is needed.
pyproject.toml
[tool.pytest.ini_options]asyncio_mode = "auto"testpaths = ["tests"]markers = [ "integration: tests that hit live HF API (deselect with '-m not integration')",]
1
Install dev dependencies
Dev dependencies are in the dev group and are included by default with uv sync.
uv sync
This installs pytest, pytest-asyncio, pytest-aiohttp, boto3, and awscli.
2
Run all unit tests
Run the full test suite, excluding integration tests that require a live HF API connection.
uv run pytest -m "not integration"
3
Run integration tests (optional)
Integration tests hit the live Hugging Face API and require a valid HF_TOKEN.
HF_TOKEN=hf_xxxxx uv run pytest -m integration
Integration tests create and delete real HF Storage Buckets. Use a token scoped to a test account or namespace. The conftest.py fixture skips integration tests automatically with pytest.skip() if HF_TOKEN is not set.
@pytest.fixturedef random_bytes() -> bytes: """200 KB of deterministic pseudo-random data (good for CDC tests).""" return os.urandom(200 * 1024)@pytest.fixturedef small_bytes() -> bytes: """1 KB payload — fits in a single CDC chunk.""" return os.urandom(1024)@pytest.fixture(scope="session")def hf_token() -> str: """HF token from env (required for integration tests).""" token = os.environ.get("HF_TOKEN", "") if not token: pytest.skip("HF_TOKEN not set — skipping integration test") return token
Because asyncio_mode = "auto" is set globally, any async def test function is automatically run under asyncio. There is no need for @pytest.mark.asyncio:
# No decorator neededasync def test_put_and_get_object(bridge) -> None: result = await bridge.put_object("my-bucket", "hello.txt", b"hello") assert "ETag" in result data = await bridge.get_object("my-bucket", "hello.txt") assert data == b"hello"
Annotate any test that calls a live HF endpoint with @pytest.mark.integration. The test will be skipped automatically in environments without HF_TOKEN:
@pytest.mark.integrationclass TestBucketOperations: async def test_create_and_delete_bucket(self, bridge) -> None: bucket_name = f"pytest-{int(time.time()) % 100000}" try: await bridge.create_bucket(bucket_name) info = await bridge.head_bucket(bucket_name) assert info is not None finally: await bridge.delete_bucket(bucket_name)