Files
VideoDetect/tests/test_story_07.py
T
2026-08-10 18:36:57 -04:00

96 lines
3.6 KiB
Python

import csv
import io
import json
import sys
import tempfile
import unittest
from pathlib import Path
from unittest.mock import MagicMock
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
import review_export
def _make_db(rows):
db = MagicMock()
db.fetchall.return_value = rows
return db
class Story07ReviewExportTests(unittest.TestCase):
_ROWS = [
{
"video_id": 1, "file_path": "/data/input/a.mp4",
"confidence_score": 0.62, "routing_decision": "REVIEW",
"model_version": "v1.0", "ground_truth": True,
"annotated_at": None, "notes": "ok",
"confidence_scores": json.dumps([0.60, 0.62, 0.65]),
},
]
def test_fetch_annotated_passes_correct_where_clause(self):
db = _make_db(self._ROWS)
review_export.fetch_annotated(db, annotated_only=True, model_version="v1.0")
call_args = db.fetchall.call_args
sql = call_args[0][0]
self.assertIn("rq.annotated = TRUE", sql)
self.assertIn("v.model_version = %s", sql)
def test_fetch_annotated_normalises_confidence_scores(self):
db = _make_db(self._ROWS)
records = review_export.fetch_annotated(db)
self.assertIsInstance(records[0]["contributing_frames"], list)
self.assertEqual(records[0]["contributing_frames"], [0.60, 0.62, 0.65])
def test_fetch_annotated_handles_null_confidence_scores(self):
rows = [{**self._ROWS[0], "confidence_scores": None}]
db = _make_db(rows)
records = review_export.fetch_annotated(db)
self.assertEqual(records[0]["contributing_frames"], [])
def test_export_json_writes_valid_utf8_file(self):
with tempfile.TemporaryDirectory() as tmpdir:
records = review_export.fetch_annotated(_make_db(self._ROWS))
path = review_export.export_json(records, f"{tmpdir}/out.json")
loaded = json.loads(Path(path).read_text(encoding="utf-8"))
self.assertEqual(len(loaded), 1)
self.assertEqual(loaded[0]["video_id"], 1)
self.assertTrue(loaded[0]["ground_truth"])
def test_export_csv_writes_valid_csv(self):
with tempfile.TemporaryDirectory() as tmpdir:
records = review_export.fetch_annotated(_make_db(self._ROWS))
path = review_export.export_csv(records, f"{tmpdir}/out.csv")
content = Path(path).read_text(encoding="utf-8")
reader = csv.DictReader(io.StringIO(content))
rows = list(reader)
self.assertEqual(len(rows), 1)
self.assertEqual(rows[0]["routing_decision"], "REVIEW")
# contributing_frames should be a JSON string in CSV
frames = json.loads(rows[0]["contributing_frames"])
self.assertEqual(frames, [0.60, 0.62, 0.65])
def test_export_csv_empty_returns_empty_file(self):
with tempfile.TemporaryDirectory() as tmpdir:
path = review_export.export_csv([], f"{tmpdir}/empty.csv")
self.assertEqual(Path(path).read_text(), "")
def test_ground_truth_filter_appears_in_query(self):
db = _make_db([])
review_export.fetch_annotated(db, ground_truth=False)
sql = db.fetchall.call_args[0][0]
self.assertIn("rq.ground_truth = %s", sql)
class Story07AppSyntaxTest(unittest.TestCase):
def test_app_module_compiles(self):
"""Ensure ui/app.py has no syntax errors."""
app_path = Path(__file__).resolve().parents[1] / "ui" / "app.py"
source = app_path.read_text(encoding="utf-8")
compile(source, str(app_path), "exec")
if __name__ == "__main__":
unittest.main()