Story 7
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user