""" Tests for the Focus Group Response Service """ import unittest from unittest.mock import patch, MagicMock from app.services.focus_group_response_service import ( generate_persona_response, FocusGroupResponseError, _format_persona_details, _format_previous_messages ) from app.services.llm_service import LLMServiceError class TestFocusGroupResponseService(unittest.TestCase): """Test cases for the Focus Group Response Service""" def test_format_previous_messages(self): """Test formatting previous messages""" # No messages self.assertEqual(_format_previous_messages([]), "No previous messages.") # With messages messages = [ {"senderId": "moderator", "text": "Welcome everyone!", "type": "question"}, {"senderId": "system", "text": "New participant joined", "type": "system"}, {"senderId": "persona-123", "text": "Hello, I'm excited to be here", "type": "response"} ] formatted = _format_previous_messages(messages) self.assertIn("MODERATOR (moderator): Welcome everyone!", formatted) self.assertIn("SYSTEM: New participant joined", formatted) self.assertIn("persona-123: Hello, I'm excited to be here", formatted) # Many messages (should be limited to 50) many_messages = [{"senderId": f"person-{i}", "text": f"Message {i}"} for i in range(60)] formatted = _format_previous_messages(many_messages) # Should only contain the 50 most recent messages self.assertEqual(formatted.count("\n") + 1, 50) def test_format_persona_details(self): """Test formatting persona details""" # Basic persona basic_persona = { "name": "John Doe", "age": "30-35", "gender": "Male", "occupation": "Software Engineer", "education": "Bachelor's Degree", "location": "San Francisco, USA", "personality": "Analytical and introverted" } formatted = _format_persona_details(basic_persona) for key, value in basic_persona.items(): self.assertIn(f"{key.title()}: {value}", formatted) # Complex persona with OCEAN traits complex_persona = { **basic_persona, "oceanTraits": { "openness": 80, "conscientiousness": 70, "extraversion": 30, "agreeableness": 60, "neuroticism": 40 }, "goals": ["Learn new skills", "Get promoted"], "frustrations": ["Bureaucracy", "Meetings"], "motivations": ["Technical excellence", "Impact"], "thinkFeelDo": { "thinks": ["How can I optimize this?", "What's the underlying pattern?"], "feels": ["Excited by technical challenges", "Frustrated by inefficiency"], "does": ["Researches solutions thoroughly", "Creates detailed plans"] } } formatted = _format_persona_details(complex_persona) # Check OCEAN traits self.assertIn("OCEAN Traits:", formatted) self.assertIn("- Openness: 80/100", formatted) # Check goals self.assertIn("Goals:", formatted) for goal in complex_persona["goals"]: self.assertIn(f"- {goal}", formatted) # Check think/feel/do self.assertIn("Thinks:", formatted) self.assertIn("Feels:", formatted) self.assertIn("Does:", formatted) @patch('app.services.focus_group_response_service.LLMService.generate_content') def test_generate_persona_response(self, mock_generate_content): """Test generating a persona response""" # Setup test data persona = { "name": "Jane Doe", "age": "30-35", "gender": "Female", "occupation": "Product Manager", "education": "Master's Degree", "location": "Boston, USA", "personality": "Confident and analytical" } discussion_guide = "This focus group is about product features" current_topic = "What do you think about the new dashboard?" previous_messages = [ {"senderId": "moderator", "text": "Welcome everyone", "type": "system"}, {"senderId": "moderator", "text": "Let's discuss the dashboard", "type": "question"} ] # Mock response mock_generate_content.return_value = "I find the dashboard intuitive and well-organized." # Test function response = generate_persona_response( persona=persona, current_topic=current_topic, previous_messages=previous_messages, temperature=0.5 ) # Assertions self.assertEqual(response, "I find the dashboard intuitive and well-organized.") mock_generate_content.assert_called_once() # Check prompt content call_args = mock_generate_content.call_args[1] self.assertEqual(call_args["temperature"], 0.5) prompt = call_args["prompt"] # Prompt should contain persona details self.assertIn("Name: Jane Doe", prompt) self.assertIn("Gender: Female", prompt) # Prompt should contain discussion guide self.assertIn("This focus group is about product features", prompt) # Prompt should contain current topic self.assertIn("What do you think about the new dashboard?", prompt) # Prompt should contain previous messages self.assertIn("MODERATOR (moderator): Let's discuss the dashboard", prompt) @patch('app.services.focus_group_response_service.LLMService.generate_content') def test_generate_persona_response_error(self, mock_generate_content): """Test error handling in persona response generation""" # Setup mock to raise an exception mock_generate_content.side_effect = LLMServiceError("LLM service unavailable") # Test error propagation with self.assertRaises(FocusGroupResponseError) as context: generate_persona_response( persona={"name": "Test Persona"}, current_topic="Test topic", previous_messages=[] ) self.assertIn("Error generating persona response", str(context.exception)) if __name__ == '__main__': unittest.main()