A newer version of the Gradio SDK is available: 6.20.0
Testing Guide β Color-UX-Access
HF Space containers cannot run a browser. Playwright is used locally for screenshots but tests are source-inspection only β no live browser in CI.
For test setup (venv, uv install), see docs/DEVELOPMENT.md.
Testing Philosophy
Tests use a layered approach, from fast to slow:
| Category | Marker | What it tests | Duration |
|---|---|---|---|
| Smoke | smoke |
Import, module load, CVD config, Gradio apps loadable | <10s |
| Pipeline | pipeline |
Full imageβCVDβWCAG report with mocked VLM | <30s |
| Slow | slow |
Real VLM calls, needs HF_TOKEN | 60-90s |
Source inspection tests verify structural properties that mocks miss β e.g., isinstance(file_obj, bytes) check for GradioFile binary type, Modal app GPU config, Gradio 6 theme placement in launch() not Blocks().
Running Tests
uv run pytest -v # all tests (smoke + pipeline) β no network, no GPU
uv run pytest -m smoke # fast: imports + smoke only (<10s)
uv run pytest -m pipeline # full pipeline with mocked VLM (<30s)
uv run pytest tests/test_app_space.py -v # single file
uv run pytest tests/test_app_space.py::test_cvd_gallery_generates_10_types -v # single test
Test Structure
tests/
βββ conftest.py Shared fixtures (img_factory, cvd_img_factory, mock_vlm_factory)
βββ fixtures/ Synthetic UI screenshots β generated by generate_fixtures.py
β βββ button_panel_accessible.png
β βββ button_panel_color_only.png
β βββ status_badges_accessible.png
β βββ status_badges_color_only.png
β βββ form_validation_accessible.png
β βββ form_validation_color_only.png
β βββ *.png Plus deuteranopia/protanopia/tritanopia variants per original
βββ test_smoke.py All core imports work, CVD variants correct, Gradio apps loadable
βββ test_capture.py capture module contract: take_screenshot exists + correct signature
βββ test_app_space.py Integration: CVD gallery, WCAG report, Gradio 6 theme launch
βββ test_gradio_binary.py Source inspection: Gradio File binary type handling
βββ test_modal_app.py Source inspection: Modal app structure (GPU, secrets, base URL)
Shared Fixtures (from conftest.py)
All fixtures are auto-discovered by pytest β import them directly in tests.
img_factory
def test_something(img_factory):
img = img_factory(640, 480, seed=42) # deterministic random PIL Image
cvd_img_factory
def test_cvd_simulation(cvd_img_factory):
img, simulate = cvd_img_factory(200, 100, seed=42)
deut = simulate(img, 'deuteranopia')
assert deut.size == img.size
mock_vlm_factory
def test_report_passes(mock_vlm_factory):
result = mock_vlm_factory(passes=True)
assert result['passes'] is True
assert result['findings'] == []
sample_button_panel
def test_cvd_confuses_buttons(sample_button_panel, cvd_img_factory):
img = sample_button_panel
_, simulate = cvd_img_factory()
deut = simulate(img, 'deuteranopia')
# Green (Confirm) and red (Cancel) buttons β visually similar for CVD
ten_type_gallery
def test_gallery_types(ten_type_gallery):
assert len(ten_type_gallery) == 7
TDD Pattern: RED β GREEN β REFACTOR
# 1. Write a failing test
uv run pytest tests/test_capture.py::test_take_screenshot_signature -v
# β RED if not yet implemented
# 2. Implement the feature
# create color_ux_access/capture.py with take_screenshot(page, url, timeout=60000)
# 3. Run again β verify GREEN
uv run pytest tests/test_capture.py -v
# 4. Refactor if needed
For new features:
# tests/test_new_feature.py
def test_feature_does_x():
from color_ux_access.module import function
result = function(input)
assert expected_output in result
Source Inspection Tests
Tests that verify source code structure rather than runtime behavior:
# tests/test_gradio_binary.py β verify GradioFile bytes handling
def test_analyze_screenshot_handles_bytes():
source = pathlib.Path("color_ux_access/modal_app.py").read_text()
assert "isinstance(file_obj, bytes)" in source
# tests/test_modal_app.py β verify Modal app structure
def test_base_url_correct():
source = pathlib.Path("color_ux_access/modal_app.py").read_text()
assert "router.huggingface.co/v1" in source
CI Integration
No CI configured yet. For now, run uv run pytest before every commit locally.
# .github/workflows/test.yml (future)
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
with:
python-version: "3.12"
- run: uv sync --extra dev
- run: uv run pytest -m smoke
Fixture Generation
Generate synthetic UI screenshots for local testing:
PYTHONPATH=. python tests/generate_fixtures.py
Each original image gets CVD-simulated variants (deuteranopia, protanopia, tritanopia). Fixture pairs:
button_panel_color_only.pngvsbutton_panel_accessible.pngβ CVD-confusable buttonsstatus_badges_color_only.pngvsstatus_badges_accessible.pngβ CVD-invisible distinctionsform_validation_color_only.pngvsform_validation_accessible.pngβ CVD-invisible error states