test: enforce 80% pytest coverage gate across all 6 Python domains (#441)#590
Conversation
- Add 79 unit tests across config, csrf, auth, storage, services - Enable branch coverage and per-file coverage reports - Per-file coverage: csrf 100%, paths 100%, annotation_service 93% - Refs #441 ✅ - Generated by Copilot
- share make_asgi_request helper in tests/conftest.py (IV-003) - replace bare-expression assertion in test_csrf (IV-004) - drive provider selection via public require_auth (IV-002) - assert AnnotationService construction via behavior round-trip (IV-001) - replace datetime.utcnow with timezone-aware now (IV-005) 🧪 - Generated by Copilot
- replace datetime.utcnow() with datetime.now(UTC) in tests/api/test_annotations.py - skip HDF5 video test when neither ffmpeg nor cv2 available - tighten hypothesis strategy in test_valid_nested_ids_accepted 🧪 - Generated by Copilot
…dataset - add 43 tests covering scan, sync, video resolve, hdf5 helpers, close - raise blob_dataset.py coverage from baseline to 89% 🧪 - Generated by Copilot
- add 13 tests covering _extract_features, cluster, _simple_clustering, dataclasses - raise clustering.py coverage from 20.45% to 98.48% 🧪 - Generated by Copilot
- cover _load_info defaults, _find_episode_location, list_episodes_with_meta - cover load_episode qpos/qvel aliases and zero-fill paths - raise lerobot_loader.py coverage from 22.77% to 90.43% 🧪 - Generated by Copilot
- cover discover, list_episodes, load_episode, get_trajectory paths via FakeLoader injection - cover get_frame_image ffmpeg/cv2 fallback and get_video_path/get_cameras error paths - raise lerobot_handler.py coverage from 25.00% to 96.76% 🧪 - Generated by Copilot
- cover _get_model cache hit and ImportError branches - cover get_cached, clear_cache, detect_frame box parsing including unknown class - cover detect_episode skips, exception handling, class summary, cache write, and singleton accessor - raise detection_service.py coverage from 48.55% to 100.00% 🧪 - Generated by Copilot
- cover detect short-input early return and constant velocity branch - cover velocity spikes, unexpected stop severity tiers and start/end exclusion - cover oscillation, force spike, gripper failure and joint limit detectors - cover _group_consecutive empty and split paths and _zscore_to_severity tiers - raise anomaly_detection.py coverage from 54.55% to 99.57% 🧪 - Generated by Copilot
- Cover validation, blob sync helpers, blob discovery, video streaming, eviction, list_datasets pruning, and capability flags - Cover prefetch scheduling guards, episode/trajectory cache paths, dataset path traversal, and invalidate_episode_cache - Cover get_video_file_path branches (no handler, lerobot, hdf5 upload, missing cache) and singleton get_dataset_service - Raises src/api/services/dataset_service/service.py coverage from 37.03% to 83.08% 🧪 - Generated by Copilot
- Adds tests/test_joint_config_router.py covering per-dataset and global joint configuration GET/PUT endpoints plus module helpers - Lifts coverage of src/api/routers/joint_config.py from 42.42% to 95.96% - Remaining uncovered lines (122, 146) are defensive double-checks unreachable behind SAFE_DATASET_ID_PATTERN 🧪 - Generated by Copilot
- Adds tests/test_ai_analysis_router.py covering trajectory analysis, anomaly detection, episode clustering, and annotation suggestion endpoints - Lifts coverage of src/api/routes/ai_analysis.py from 45.62% to 95.00% 🧪 - Generated by Copilot
- Adds tests/test_export_router.py covering sync export, SSE streaming, and preview endpoints - Lifts coverage of src/api/routers/export.py from 47.74% to 91.46% 🧪 - Generated by Copilot
- Adds tests/test_datasets_router.py covering capabilities, episodes, trajectory, frames, cameras, video file/blob streaming with HEAD and Range support, cache stats, and warm-cache endpoints - Lifts coverage of src/api/routers/datasets.py from 48.72% to 100.00% 🧪 - Generated by Copilot
- add evaluation-pytests reusable workflow job alongside other pytest jobs - add evaluation-pytests to release-please needs for parity with pr-validation.yml 🔧 - Generated by Copilot
…anches - Fix function-local import monkeypatches via string-form setattr - Rebuild ffmpeg success-path FakeProc to write output file in wait() - Remove orphaned assertion tail in get_loader test - Add cv2 success-path test via sys.modules injection with FakeWriter - Coverage 81.23% -> 93.49% 🧪 - Generated by Copilot
- Add StorageError wrap test for _download_file exception path - Add string-tasks branch and parse-error wrap tests for get_dataset_info - Add parquet discovery success path with ValueError and non-parquet skip - Add StorageError re-raise tests for get_dataset_info, list_episodes, get_episode_data - Add unexpected-exception wrap test for get_episode_data - Coverage: huggingface.py 87.74%% -> 92.90%% 🧪 - Generated by Copilot
…aged identity - Add ImportError test for missing azure-storage-blob SDK - Add managed identity branch test for _get_client - Add invalid JSON, HttpResponseError, and unexpected exception wraps for get_annotation - Add HttpResponseError and unexpected exception wraps for save_annotation - Add malformed filename skip and error wraps for list_annotated_episodes - Add HttpResponseError and unexpected exception wraps for delete_annotation - Add close test releasing client and idempotent no-op when never created - Coverage: azure.py 69.11%% -> 93.50%% 🧪 - Generated by Copilot
- Add edge-case tests for crop, resize, brightness, contrast, saturation, hue, gamma, and color filter validation paths - Add tests for apply_color_adjustment, apply_transform dispatch, apply_transforms_batch, apply_camera_transforms, and get_output_dimensions - Lift image_transform.py coverage from 73.47%% to 97.62%% 🧪 - Generated by Copilot
- Add tests for HDF5Loader covering load_all_frames, load_single_frame, file discovery, caching, and error paths - Fix stale regex assertion in test_find_episode_file_missing_raises to match current 'No HDF5 file found' error message - Brings src/api/services/hdf5_loader.py coverage to 95.85%% 🧪 - Generated by Copilot
…zers - Add tests/test_validation_branches.py exercising dependency factory closures directly - Cover _sanitize_nested_value recursion across list, tuple, set, dict - Cover SanitizedModel CRLF stripping in nested fields - Cover validate_safe_string empty rejection and pattern compilation paths - Cover range_header_param branches: none, prefix mismatch, open-ended, bounded, invalid - Lift src/api/validation.py coverage from 85.53% to 100% 🧪 - Generated by Copilot
- Add tests/api/test_analysis.py with TestClient cases for /trajectory-quality and /anomaly-detection - Push src/api/routers/analysis.py from 75.00% to 100% 🧪 - Generated by Copilot
- Add tests/test_config_branches.py exercising error paths and env-driven defaults - Hold src/api/config.py at 100% combined coverage 🧪 - Generated by Copilot
- Add Pydantic model tests for DetectionRequest.validate_frames - Cover None, valid, and negative-frame paths - Push src/api/models/detection.py from 88.89% to 100% 🧪 - Generated by Copilot
- Add tests for makedirs OSError, atomic-write cleanup, malformed filename skip - Cover listdir/remove failure paths and missing-directory early return - Add cleanup-skip-unlink and empty-directory branch coverage - Push src/api/storage/local.py from 78.35% to 98.97% 🧪 - Generated by Copilot
- add SecurityHeadersMiddleware tests for /docs, /redoc, /openapi.json bypass - add ContentSizeLimitMiddleware tests for malformed Content-Length and streaming overflow - raise src/api/middleware.py from 86.84% to 98.68% 🧪 - Generated by Copilot
- add tests for run-detection 404, success, and 500 unexpected-error paths - add tests for GET cached detections and DELETE clear-cache endpoints - raise src/api/routers/detection.py to 97.83% (44 stmts, 1 missing) 🧪 - Generated by Copilot
- add tests for GET/PUT/DELETE annotations 404 and success paths - add tests for auto-analysis and summary endpoints - raise src/api/routers/annotations.py from 26.15% to 100% 🧪 - Generated by Copilot
- convert async tests to sync wrappers using asyncio.run for compatibility without pytest-asyncio - exercise CRUD, auto-analysis flag detection (jitter/hesitation/correction), and summary aggregation - raise src/api/services/annotation_service.py from 14.29% to 88.10% 🧪 - Generated by Copilot
- Convert async provider tests to sync wrappers using asyncio.run - Cover ApiKeyProvider, EasyAuthProvider, JwtProvider, and require_auth/require_role paths - Validate provider factory dispatch and reset_auth_provider singleton behavior 🧪 - Generated by Copilot
🎨 - Generated by Copilot
🎨 - Generated by Copilot
|
@WilliamBerryiii noting here that we may want to rebase and update some of the tests for dataviewer, with the extent of changes being added by @akzaidi in PR #591 (merge that before this one?). Believe it makes more sense. Great addition here in any case! |
- extract four @given methods from TestValidateDatasetIdProperties class - convert to standalone module-level test functions - resolves CodeQL py/iteration-of-non-iterable false positive - Generated by Copilot
- extract four @given methods from TestValidateDatasetIdProperties class - convert to standalone module-level test functions - resolves CodeQL py/iteration-of-non-iterable false positive ♻️ - Generated by Copilot
- remove unreachable except clause in storage/test_base.py - replace bare assertions and dead branches in api/test_labels.py - drop redundant assignments and unused locals in dataset/hdf5/middleware tests - tighten assertion in training lerobot checkpoint test 🎨 - Generated by Copilot
- remove unreachable except clause in storage/test_base.py - replace bare assertions and dead branches in api/test_labels.py - drop redundant assignments and unused locals in dataset/hdf5/middleware tests - tighten assertion in training lerobot checkpoint test 🎨 - Generated by Copilot
Yes. |
🎨 - Generated by Copilot
🎨 - Generated by Copilot
rezatnoMsirhC
left a comment
There was a problem hiding this comment.
Thank you for the thorough coverage work here. The CI gate additions are clean and the new test suite is impressively comprehensive. Left a few comments below.
…ackend-coverage # Conflicts: # data-management/viewer/backend/tests/test_lerobot_handler.py # data-management/viewer/backend/tests/test_lerobot_loader.py
- Convert manual asyncio.run wrappers to native async tests - Rely on pytest-asyncio asyncio_mode=auto for execution - Improves readability and prepares for additional async coverage 🤖 - Generated by Copilot
- Canonical launch tests live alongside training package - Removes duplicate to avoid divergence 🤖 - Generated by Copilot
…e to 90 - Add rationale comments for deadline=None on slow hypothesis tests - Raise dataviewer backend --cov-fail-under from 80 to 90 🤖 - Generated by Copilot
- test_detection: tolerate broken ultralytics/torch installs (AttributeError) - test_lerobot_handler: add get_tasks() to FakeLoader (post-merge API) - test_hdf5_handler: probe avc1 codec at runtime, skip if unavailable on Windows 🤖 - Generated by Copilot
- Resolved conflicts by keeping refactored test files (async wrappers, get_tasks fix, codec probe) over remote's style-only edits to the pre-refactor versions - Retained deletion of duplicate training/tests/test_rl_launch.py - Auto-merged labels.py, test_labels.py, test_config_branches.py, test_lerobot_loader.py, test_property_based.py 🤖 - Generated by Copilot
- Convert 49 sync wrapper + asyncio.run(_run()) sites to native async def test_* - Aligns with pytest-asyncio auto mode used elsewhere in suite - Preserves import asyncio (used by test_creates_task_when_loop_running) 🤖 - Generated by Copilot
|
Follow-up: converted the orchestrator tests to the native
🤖 - Generated by Copilot |
- Capture _prefetch() coroutine and explicitly close it in the RuntimeError branch of _schedule_prefetch to eliminate "coroutine was never awaited" warning when no event loop is running - Apply ruff format to backend test files to satisfy CI lint check 🤖 - Generated by Copilot
katriendg
left a comment
There was a problem hiding this comment.
Nice one, valuable addition to our code coverage across.
- Align local pytest config with CI workflow already enforcing 80% - Remove stale TODO; capture/ now ships config, models, scripts modules - Resolve PR #590 review nit (thread r3180127646) 🤖 - Generated by Copilot
Summary
Brings the entire repository to ≥80% pytest coverage across all six Python domains and enforces that floor in CI. Closes #441.
Originally scoped to the dataviewer backend, the work expanded after audit to cover every Python domain in the repo. Each domain now has empirically verified coverage well above the 80% gate, and every main pytest workflow now fails the build when coverage drops below 80%.
Per-Domain Coverage (verified locally)
data-pipeline.github/workflows/pytest-data-pipeline.ymldata-management/tools.github/workflows/pytest-dm-tools.ymlevaluation(sil+metrics).github/workflows/evaluation-pytests.ymlfleet-deployment/inference.github/workflows/pytest-inference.ymltraining.github/workflows/pytest-training.ymldata-management/viewer(back).github/workflows/dataviewer-backend-pytests.ymlCI Gates Enforced
All six main pytest workflows now pass
--cov-fail-under=80:.github/workflows/pytest-training.yml.github/workflows/pytest-inference.yml.github/workflows/pytest-dm-tools.yml.github/workflows/pytest-data-pipeline.yml.github/workflows/dataviewer-backend-pytests.yml.github/workflows/evaluation-pytests.yml(gated viaevaluation/pyproject.tomladdopts:--cov=sil --cov=metrics --cov-fail-under=80)Notable Changes
training/tests/(SKRL, RSL-RL, Azure smoke),fleet-deployment/inference/tests/(ACT inference node, plotting + robot-types Hypothesis suites),evaluation/(sil + metrics),data-pipeline/,data-management/tools/, and the dataviewer backend.deadline=Noneapplied where flakes were observed.importlib.utilto support test discovery.data-pipeline/uv.lockadded for reproducible builds (matches existingevaluation/uv.lockconvention).Commit Composition (59 commits)
testcifixchorefeatopsFiles Changed
108 files changed, 15,464 insertions(+), 1,497 deletions(-).
Distribution by top-level directory:
data-management.githubtrainingdocsdata-pipelineevaluationfleet-deploymentValidation
Each domain was run locally with
--cov-fail-under=80; all passed. CI workflows on this branch will re-validate on push.Deferred / Follow-Up
.github/workflows/fuzz-regression-tests.ymlcollects coverage but does not yet enforce--cov-fail-under=80(separate concern; tracked for follow-up).logs/cleanup of stale local coverage artifacts.Related
Closes #441