call-qa-processing / backend /test_pipeline_progress.py
aniketqxp's picture
fix: harden forced call processing
123559e verified
Raw
History Blame Contribute Delete
7.29 kB
import os
import unittest
from types import SimpleNamespace
from unittest.mock import patch
from app.routers.calls import _evaluation_summary, _pipeline_progress
def _job(status, stage):
return SimpleNamespace(status=status, stage=stage)
class PipelineProgressTests(unittest.TestCase):
def test_active_stage_completes_every_prior_enabled_step(self):
with patch.dict(
os.environ,
{
"ENABLE_ACOUSTIC": "1",
"EVALUATOR_V2_SHADOW": "1",
},
):
progress = _pipeline_progress(
_job("processing", "evaluating_v2_requirements")
)
states = {
stage["id"]: stage["state"]
for stage in progress["stages"]
}
self.assertEqual(states["evaluation"], "completed")
self.assertEqual(states["evidence"], "completed")
self.assertEqual(states["requirements"], "active")
self.assertEqual(states["findings"], "pending")
self.assertEqual(states["publish"], "pending")
self.assertEqual(
progress["current_stage_label"],
"Assess requirements",
)
def test_forced_transcription_starts_in_the_queue(self):
progress = _pipeline_progress(
_job("queued", "force_uploaded")
)
self.assertEqual(progress["current_stage_id"], "queued")
self.assertEqual(progress["percent"], 0)
self.assertEqual(progress["stages"][0]["state"], "active")
def test_disabled_optional_stages_are_marked_skipped(self):
with patch.dict(
os.environ,
{
"ENABLE_ACOUSTIC": "0",
"EVALUATOR_V2_SHADOW": "0",
},
):
progress = _pipeline_progress(
_job("processing", "evaluating")
)
states = {
stage["id"]: stage["state"]
for stage in progress["stages"]
}
self.assertEqual(states["acoustic"], "completed")
self.assertEqual(states["evidence"], "skipped")
self.assertEqual(states["requirements"], "skipped")
self.assertEqual(states["findings"], "skipped")
self.assertEqual(states["decision"], "skipped")
self.assertEqual(states["presentation"], "skipped")
self.assertEqual(states["evaluation"], "active")
def test_success_marks_enabled_pipeline_complete(self):
with patch.dict(
os.environ,
{
"ENABLE_ACOUSTIC": "1",
"EVALUATOR_V2_SHADOW": "0",
},
):
progress = _pipeline_progress(_job("succeeded", "done"))
enabled_states = [
stage["state"]
for stage in progress["stages"]
if stage["state"] != "skipped"
]
self.assertEqual(set(enabled_states), {"completed"})
self.assertEqual(progress["percent"], 100)
def test_failure_marks_current_stage(self):
with patch.dict(
os.environ,
{
"ENABLE_ACOUSTIC": "1",
"EVALUATOR_V2_SHADOW": "0",
},
):
progress = _pipeline_progress(
_job("failed", "segmenting")
)
current = next(
stage
for stage in progress["stages"]
if stage["id"] == "segments"
)
self.assertEqual(current["state"], "failed")
class EvaluationSummaryTests(unittest.TestCase):
def test_success_uses_evaluator_presentation_not_legacy_scores(self):
run = SimpleNamespace(
status="succeeded",
created_at=None,
payload={
"status": "succeeded",
"evaluator_version": "v2-policy-test",
"decision": {
"decision_status": "complete",
"attention_required": True,
},
"presentation": {
"state": "needs_attention",
"evaluation_status": "complete",
"attention_required": True,
"manager_questions": [
{
"question_id": "call.request",
"answer": "yes",
"summary": "Request confirmed.",
"evidence_ids": ["evidence-request"],
},
{
"question_id": "call.process",
"answer": "partly",
"summary": "One process concern.",
"evidence_ids": ["evidence-process"],
},
{
"question_id": "call.experience",
"answer": "yes",
"summary": "Experience handled.",
"evidence_ids": [],
},
{
"question_id": "call.outcome",
"answer": "yes",
"summary": "Outcome confirmed.",
"evidence_ids": ["evidence-outcome"],
},
],
"primary_reasons": [{"finding_id": "finding-a"}],
"additional_reason_count": 1,
"checklist": [
{"status": "demonstrated"},
{"status": "incorrect"},
{"status": "not_demonstrated"},
],
"acoustic_context": {
"status": "limited",
"coverage_label": "Audio support on 2 of 3 segments",
},
},
},
)
summary = _evaluation_summary("call-a", "banking", run)
self.assertTrue(summary["evaluation_available"])
self.assertTrue(summary["attention_required"])
self.assertEqual(summary["evaluation_state"], "needs_attention")
self.assertEqual(summary["result"], "review")
self.assertEqual(summary["aspects"]["request"]["state"], "ok")
self.assertEqual(summary["aspects"]["process"]["state"], "concern")
self.assertEqual(summary["concern_count"], 2)
self.assertEqual(summary["checklist_counts"]["demonstrated"], 1)
self.assertEqual(summary["checklist_counts"]["incorrect"], 1)
self.assertEqual(
summary["checklist_counts"]["not_demonstrated"],
1,
)
self.assertEqual(summary["acoustic_status"], "limited")
def test_domain_without_profile_is_not_reported_as_evaluated(self):
summary = _evaluation_summary(
"call-b",
"health",
SimpleNamespace(
status="unsupported_domain",
created_at=None,
payload={"status": "unsupported_domain"},
),
)
self.assertFalse(summary["evaluation_available"])
self.assertTrue(summary["evaluation_supported"])
self.assertEqual(summary["evaluation_state"], "unsupported")
if __name__ == "__main__":
unittest.main()