capit / backend /tests /test_app.py
capit-deploy
deploy capit backend
a5ec84d
Raw
History Blame Contribute Delete
2.54 kB
"""Stage 6.1 — backend API. Needs the local artifact + cached BLIP; skips cleanly otherwise."""
import io
import sys
from pathlib import Path
import pytest
from PIL import Image
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from app import ARTIFACT_DIR, app
from fastapi.testclient import TestClient
pytestmark = pytest.mark.skipif(
not (ARTIFACT_DIR / "capit-sat.pt").exists(),
reason="no local serving artifact; run scripts/export_artifact.py first",
)
@pytest.fixture(scope="module")
def client():
with TestClient(app) as c:
yield c
def _png(size=(64, 48), mode="RGB", exif=None) -> bytes:
img = Image.new(mode, size, "red")
buf = io.BytesIO()
if exif is not None:
img.save(buf, format="JPEG", exif=exif)
else:
img.save(buf, format="PNG")
return buf.getvalue()
def test_health(client):
assert client.get("/health").json() == {"status": "ok"}
def test_caption_happy_sat(client):
r = client.post("/caption?model=sat&beam=3", files={"file": ("x.png", _png(), "image/png")})
assert r.status_code == 200
sat = r.json()["sat"]
assert sat["caption"] and len(sat["words"]) == len(sat["attention"])
assert all(len(row) == 196 for row in sat["attention"])
assert set(sat["crop"]) == {"x", "y", "w", "h"}
assert sat["beams"][0]["caption"]
def test_caption_both_has_blip(client):
r = client.post("/caption?model=both", files={"file": ("x.png", _png(), "image/png")})
body = r.json()
assert r.status_code == 200 and body["blip"]["caption"] and body["sat"]["caption"]
def test_junk_bytes_is_422(client):
r = client.post("/caption?model=sat", files={"file": ("x.png", b"not an image", "image/png")})
assert r.status_code == 422
def test_oversized_is_413(client):
big = b"\xff" * (8 * 1024 * 1024 + 1)
r = client.post("/caption?model=sat", files={"file": ("x.png", big, "image/png")})
assert r.status_code == 413
def test_rgba_accepted(client):
r = client.post("/caption?model=sat", files={"file": ("x.png", _png(mode="RGBA"), "image/png")})
assert r.status_code == 200
def test_exif_orientation_applied(client):
exif = Image.Exif()
exif[0x0112] = 6 # rotate 90 CW: a saved 400x200 displays upright as 200x400 (portrait)
r = client.post("/caption?model=sat", files={"file": ("x.jpg", _png((400, 200), exif=exif), "image/jpeg")})
crop = r.json()["sat"]["crop"]
assert crop["w"] > crop["h"] # portrait-upright crops wider in fractions; ignoring EXIF would flip this