세션 평가와 교수자 분석 보강
This commit is contained in:
parent
5c4ac04e06
commit
fe2796f05a
51 changed files with 4928 additions and 240 deletions
|
|
@ -5,6 +5,8 @@ from __future__ import annotations
|
|||
import unittest
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from fastapi import HTTPException
|
||||
|
||||
from .deps import Principal, Role
|
||||
from .routes import teacher
|
||||
from .services import state_machine
|
||||
|
|
@ -244,6 +246,88 @@ class TeacherDashboardGrowthTest(unittest.IsolatedAsyncioTestCase):
|
|||
self.assertIn("보호요인", response.worksheet_note)
|
||||
self.assertEqual(response.worksheet_reviewed_at, "2026-06-27T10:05:00Z")
|
||||
|
||||
async def test_learner_analysis_returns_full_ordered_history(self) -> None:
|
||||
learner_id = "00000000-0000-0000-0000-000000000111"
|
||||
other_learner_id = "00000000-0000-0000-0000-000000000222"
|
||||
learner_sessions = [
|
||||
_session(
|
||||
session_id=f"analysis-session-{idx}",
|
||||
session_no=idx,
|
||||
learner_id=learner_id,
|
||||
score="pos" if idx >= 5 else "neutral",
|
||||
rapport=0.1 * idx,
|
||||
technique="reflection" if idx % 2 else "open question",
|
||||
created_at=1_000.0 + idx,
|
||||
)
|
||||
for idx in range(1, 8)
|
||||
]
|
||||
sessions = [
|
||||
learner_sessions[6],
|
||||
_session(
|
||||
session_id="analysis-other-session",
|
||||
session_no=1,
|
||||
learner_id=other_learner_id,
|
||||
score="warn",
|
||||
rapport=-0.2,
|
||||
technique="advice",
|
||||
created_at=1_500.0,
|
||||
),
|
||||
*learner_sessions[:6],
|
||||
]
|
||||
principal = _principal()
|
||||
|
||||
with (
|
||||
patch.object(
|
||||
teacher.session_persistence,
|
||||
"list_sessions",
|
||||
AsyncMock(return_value=(sessions, True)),
|
||||
) as list_sessions,
|
||||
patch.object(
|
||||
teacher.session_persistence,
|
||||
"list_session_review_statuses",
|
||||
AsyncMock(
|
||||
return_value=(
|
||||
{
|
||||
"analysis-session-2": {
|
||||
"session_id": "analysis-session-2",
|
||||
"status": "closed",
|
||||
"note": "확인 완료",
|
||||
"reviewed_at": "2026-06-27T10:00:00Z",
|
||||
}
|
||||
},
|
||||
True,
|
||||
)
|
||||
),
|
||||
),
|
||||
):
|
||||
response = await teacher.learner_analysis(learner_id, principal)
|
||||
|
||||
list_sessions.assert_awaited_once_with(principal, include_turn_evaluation=True)
|
||||
self.assertEqual(response.source, "database")
|
||||
self.assertEqual(response.learner_id, learner_id)
|
||||
self.assertEqual(response.total_sessions, 7)
|
||||
self.assertEqual(response.ended_sessions, 7)
|
||||
self.assertEqual(response.pending_reviews, 6)
|
||||
self.assertEqual(response.closed_reviews, 1)
|
||||
self.assertEqual([session.session_no for session in response.sessions], [1, 2, 3, 4, 5, 6, 7])
|
||||
self.assertEqual([point.session_no for point in response.points], [1, 2, 3, 4, 5, 6, 7])
|
||||
self.assertEqual(response.sessions[1].review_status, "closed")
|
||||
explore = next(item for item in response.stage_breakdown if item.stage == "탐색")
|
||||
self.assertEqual(explore.sessions, 7)
|
||||
self.assertEqual(explore.turns, 14)
|
||||
|
||||
async def test_learner_analysis_returns_404_for_out_of_scope_learner(self) -> None:
|
||||
principal = _principal()
|
||||
with patch.object(
|
||||
teacher.session_persistence,
|
||||
"list_sessions",
|
||||
AsyncMock(return_value=([], True)),
|
||||
):
|
||||
with self.assertRaises(HTTPException) as raised:
|
||||
await teacher.learner_analysis("missing-learner", principal)
|
||||
|
||||
self.assertEqual(raised.exception.status_code, 404)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue