fashionistar-celery-queues / tests /test_ai_workflows.py
FASHIONISTAR CI/CD
🔄 Celery Queues Deploy: 4aae6106b1530c3cc7d7d64f5e3c3e1d5015691d [GitHub Actions]
27c799c
Raw
History Blame
3.97 kB
# tests/test_ai_workflows.py
"""
Unit tests for FASHIONISTAR AI LangGraph Workflows:
- MeasurementWorkflow
- RecommendationWorkflow
"""
import uuid
from unittest.mock import patch, MagicMock
from django.test import TestCase
from django.contrib.auth import get_user_model
from apps.ai.workflows.measurement import MeasurementWorkflow
from apps.ai.workflows.recommendation import RecommendationWorkflow
from apps.measurements.models.scan import BodyScanSession
from apps.measurements.models import MeasurementProfile
User = get_user_model()
class AIWorkflowsTests(TestCase):
"""Verify that both workflows compile and run successfully."""
def setUp(self):
self.user = User.objects.create_user(
email="ai_workflow_user@fashionistar.test",
password="SecurePass123!",
role="client",
)
# Create a body scan session
self.session = BodyScanSession.objects.create(
owner=self.user,
device_type="web",
scan_provider="ai_camera",
status="pending",
)
# Mock the geometry pipeline run
self.mock_geometry_result = {
"is_valid": True,
"validation_message": "Success",
"quality_score": 0.85,
"profile_fields": {
"height": 175.0,
"chest": 95.0,
"waist": 80.0,
"hips": 98.0,
"shoulder_width": 45.0,
},
"linear": {
"height": 175.0,
"shoulder_width": 45.0,
},
"circumferences": {
"chest": 95.0,
"waist": 80.0,
"hips": 98.0,
}
}
@patch("apps.ai.utils.geometry.run_full_measurement_pipeline")
@patch("apps.ai.tasks.recommendation_tasks.run_profile_recommendations.delay")
def test_measurement_workflow_success(self, mock_rec_task, mock_pipeline):
"""MeasurementWorkflow runs, saves profile, and completes session."""
mock_pipeline.return_value = self.mock_geometry_result
# Run workflow
workflow = MeasurementWorkflow()
result = workflow.execute({
"session_id": str(self.session.session_id),
"user_id": self.user.id,
"user_height_cm": 175.0,
"user_weight_kg": 70.0,
"landmarks": [{"x": 0.1, "y": 0.2, "z": 0.3} for _ in range(33)],
})
# Assertions
self.assertTrue(result["is_valid"])
self.assertEqual(result["quality_score"], 0.85)
self.assertEqual(result["errors"], [])
# Check DB updates
self.session.refresh_from_db()
self.assertEqual(self.session.status, "completed")
self.assertEqual(self.session.scan_confidence, 0.85)
# Check MeasurementProfile created
profile = MeasurementProfile.objects.filter(owner=self.user).first()
self.assertIsNotNone(profile)
self.assertEqual(profile.height, 175.0)
# Check recommendation task was fired
mock_rec_task.assert_called_once_with(
profile_id=str(profile.id),
user_id=self.user.id,
)
def test_recommendation_workflow_empty_candidates(self):
"""RecommendationWorkflow handles early exit elegantly when no candidates exist."""
# Create a measurement profile for the user
profile = MeasurementProfile.objects.create(
owner=self.user,
height=175.0,
bust=95.0,
waist=80.0,
hips=98.0,
)
workflow = RecommendationWorkflow()
result = workflow.execute({
"profile_id": str(profile.id),
"user_id": self.user.id,
})
# Assertions (should complete with empty recommendations since candidate pool is empty)
self.assertEqual(result["recommendation_ids"], [])
self.assertEqual(result["errors"], [])