Spaces:
Paused
Paused
Download tests/test_raremine/test_api_lifecycle.py from whassan/SensorflowStudio: direct link, hf CLI and curl.
- Browser
- Download file 6.13 kB
-
https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/tests/test_raremine/test_api_lifecycle.py
- Command line
-
hf download hf://spaces/whassan/SensorflowStudio/tests/test_raremine/test_api_lifecycle.py
-
curl -L -o test_api_lifecycle.py https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/tests/test_raremine/test_api_lifecycle.py
6.13 kB
| """Full API lifecycle via TestClient (in-process, no live server needed). | |
| Uses a standalone FastAPI app with only the raremine router so the test does | |
| not depend on other teams' in-progress routers in app_backend. | |
| """ | |
| from __future__ import annotations | |
| import pytest | |
| from fastapi import FastAPI | |
| from fastapi.testclient import TestClient | |
| from sensorflow.raremine.api import router | |
| from sensorflow.raremine.models import reset_store | |
| def client(tmp_path): | |
| reset_store(tmp_path) | |
| app = FastAPI() | |
| app.include_router(router) | |
| with TestClient(app) as c: | |
| yield c | |
| reset_store() | |
| def _mine(client) -> dict: | |
| r = client.post("/api/raremine/scenes/generate", json={"n": 60, "seed": 7}) | |
| assert r.status_code == 200 | |
| bank = r.json()["bank"] | |
| r = client.post("/api/raremine/mine", json={"diversity_budget": 10}) | |
| assert r.status_code == 200 | |
| return {"bank": bank, "run": r.json()} | |
| def test_full_lifecycle(client): | |
| ctx = _mine(client) | |
| assert ctx["run"]["run"]["num_track_candidates"] > 0 | |
| assert ctx["run"]["dedup_report"]["duplicates_archived"] >= 1 | |
| # status summary | |
| status = client.get("/api/raremine/status").json() | |
| assert status["bank"]["bank_id"] == ctx["bank"]["bank_id"] | |
| assert status["priority_histogram"] | |
| # candidate list + filters | |
| r = client.get("/api/raremine/candidates").json() | |
| assert r["count"] > 0 | |
| crit = client.get("/api/raremine/candidates", params={"priority": "CRITICAL"}).json() | |
| assert all(c["candidate"]["curation_priority"] == "CRITICAL" for c in crit["candidates"]) | |
| # detail + scene view | |
| first = r["candidates"][0] | |
| tcid = first["track_candidate_id"] | |
| detail = client.get(f"/api/raremine/candidates/{tcid}").json() | |
| assert detail["frame_candidates"] | |
| assert detail["lineage"] is not None | |
| scene = client.get(f"/api/raremine/candidates/{tcid}/scene").json() | |
| assert any(o["is_candidate"] for o in scene["objects"]) | |
| # track view + reports | |
| tracks = client.get("/api/raremine/tracks").json() | |
| assert tracks["count"] > 0 | |
| assert client.get("/api/raremine/dedup/report").status_code == 200 | |
| assert client.get("/api/raremine/diversity/report").status_code == 200 | |
| assert client.get("/api/raremine/reports/quantval").status_code == 200 | |
| assert client.get("/api/raremine/reports/curator").status_code == 200 | |
| assert client.get("/api/raremine/reports/improvement").status_code == 200 | |
| # approve into a rare-event dataset | |
| rev = client.post(f"/api/raremine/review/{tcid}", | |
| json={"action": "approve", "note": "confirmed", | |
| "destination": "RARE_EVENT_DATASET"}).json() | |
| assert rev["stage"] == "CURATED" | |
| assert rev["lineage"]["validation_status"] == "APPROVED" | |
| # reject another | |
| second = r["candidates"][1]["track_candidate_id"] | |
| rev = client.post(f"/api/raremine/review/{second}", | |
| json={"action": "reject", "note": "statue"}).json() | |
| assert rev["stage"] == "ARCHIVED" | |
| # destinations reflect the decisions | |
| dest = client.get("/api/raremine/destinations").json() | |
| assert "RARE_EVENT_DATASET" in dest["counts"] | |
| # explain endpoint always answers (deterministic offline fallback) | |
| ex = client.post(f"/api/raremine/candidates/{tcid}/explain").json() | |
| assert ex["status"] == "ok" | |
| assert "Separate confidences" in ex["analysis"] or ex["provider"] != "offline_deterministic" | |
| def test_leakage_guard_over_api(client): | |
| ctx = _mine(client) | |
| cands = client.get("/api/raremine/candidates").json()["candidates"] | |
| tcid = cands[0]["track_candidate_id"] | |
| # approve into a PROTECTED evaluation set | |
| rev = client.post(f"/api/raremine/review/{tcid}", | |
| json={"action": "approve", | |
| "destination": "SAFETY_CRITICAL_EVALUATION_SET"}).json() | |
| assert rev["lineage"]["protected_evaluation"] is True | |
| assert rev["lineage"]["training_eligible"] is False | |
| # silent training promotion must be blocked with 403 | |
| r = client.post("/api/raremine/governance/promote-training", | |
| json={"track_candidate_id": tcid}) | |
| assert r.status_code == 403 | |
| assert "protected evaluation set" in r.json()["detail"] | |
| lin = client.get(f"/api/raremine/lineage/{tcid}").json() | |
| assert lin["training_eligible"] is False | |
| # override without actor/reason fails | |
| r = client.post("/api/raremine/governance/override", | |
| json={"track_candidate_id": tcid, "actor": " ", "reason": ""}) | |
| assert r.status_code == 400 | |
| # explicit override (who + why) then promotion succeeds and is recorded | |
| r = client.post("/api/raremine/governance/override", | |
| json={"track_candidate_id": tcid, "actor": "safety-lead", | |
| "reason": "example rotated out of the protected eval set"}) | |
| assert r.status_code == 200 | |
| r = client.post("/api/raremine/governance/promote-training", | |
| json={"track_candidate_id": tcid, "curator": "safety-lead"}) | |
| assert r.status_code == 200 | |
| lin = r.json()["lineage"] | |
| assert lin["training_eligible"] is True | |
| assert lin["governance_overrides"][0]["actor"] == "safety-lead" | |
| def test_unapproved_promotion_blocked(client): | |
| _mine(client) | |
| cands = client.get("/api/raremine/candidates").json()["candidates"] | |
| tcid = cands[0]["track_candidate_id"] | |
| r = client.post("/api/raremine/governance/promote-training", | |
| json={"track_candidate_id": tcid}) | |
| assert r.status_code == 403 | |
| assert "unverified" in r.json()["detail"] | |
| def test_validation_errors(client): | |
| _mine(client) | |
| cands = client.get("/api/raremine/candidates").json()["candidates"] | |
| tcid = cands[0]["track_candidate_id"] | |
| assert client.post(f"/api/raremine/review/{tcid}", | |
| json={"action": "maybe"}).status_code == 400 | |
| assert client.post(f"/api/raremine/review/{tcid}", | |
| json={"action": "approve", "destination": "NOT_A_SET"}).status_code == 400 | |
| assert client.get("/api/raremine/candidates/nope-123").status_code == 404 | |