Spaces:
Sleeping
Sleeping
| # test_properties_data_models.py | |
| """ | |
| Property-based tests for Chaplain Feedback data model serialization. | |
| Tests that all data models serialize and deserialize correctly (round-trip). | |
| """ | |
| import pytest | |
| from hypothesis import given, settings | |
| from datetime import datetime | |
| from src.core.chaplain_models import ( | |
| DistressIndicator, | |
| FollowUpQuestion, | |
| ClassificationFlowResult, | |
| TaggingRecord, | |
| InteractionStepLog, | |
| INDICATOR_DEFINITIONS, | |
| ) | |
| from tests.chaplain_feedback.conftest import ( | |
| distress_indicator_strategy, | |
| follow_up_question_strategy, | |
| classification_flow_result_strategy, | |
| tagging_record_strategy, | |
| interaction_step_log_strategy, | |
| interaction_step_log_with_tagging_strategy, | |
| ) | |
| class TestDistressIndicatorRoundTrip: | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| Tests that DistressIndicator serializes and deserializes correctly. | |
| """ | |
| def test_distress_indicator_round_trip(self, indicator): | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| **Validates: Requirements 8.5** | |
| For any DistressIndicator, converting to dict and back should | |
| preserve all fields exactly. | |
| """ | |
| # Convert to dict and back | |
| indicator_dict = indicator.to_dict() | |
| restored = DistressIndicator.from_dict(indicator_dict) | |
| # Verify all fields match | |
| assert restored.indicator_text == indicator.indicator_text | |
| assert restored.category == indicator.category | |
| assert restored.subcategory == indicator.subcategory | |
| assert restored.severity == indicator.severity | |
| assert restored.confidence == indicator.confidence | |
| assert restored.definition_reference == indicator.definition_reference | |
| def test_distress_indicator_from_definition(self): | |
| """ | |
| Test creating DistressIndicator from INDICATOR_DEFINITIONS. | |
| """ | |
| # Test with a known indicator | |
| indicator = DistressIndicator.from_definition( | |
| indicator_key="excessive_guilt", | |
| indicator_text="I feel so guilty about everything", | |
| confidence=0.85 | |
| ) | |
| assert indicator.category == "Guilt" | |
| assert indicator.subcategory == "Excessive guilt" | |
| assert indicator.severity == "red" | |
| assert indicator.definition_reference == "II.D" | |
| assert indicator.confidence == 0.85 | |
| class TestFollowUpQuestionRoundTrip: | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| Tests that FollowUpQuestion serializes and deserializes correctly. | |
| """ | |
| def test_follow_up_question_round_trip(self, question): | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| **Validates: Requirements 8.5** | |
| For any FollowUpQuestion, converting to dict and back should | |
| preserve all fields exactly. | |
| """ | |
| # Convert to dict and back | |
| question_dict = question.to_dict() | |
| restored = FollowUpQuestion.from_dict(question_dict) | |
| # Verify all fields match | |
| assert restored.question_id == question.question_id | |
| assert restored.question_text == question.question_text | |
| assert restored.purpose == question.purpose | |
| class TestClassificationFlowResultRoundTrip: | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| Tests that ClassificationFlowResult serializes and deserializes correctly. | |
| """ | |
| def test_classification_flow_result_round_trip(self, result): | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| **Validates: Requirements 8.5** | |
| For any ClassificationFlowResult, converting to dict and back should | |
| preserve all fields exactly. | |
| """ | |
| # Convert to dict and back | |
| result_dict = result.to_dict() | |
| restored = ClassificationFlowResult.from_dict(result_dict) | |
| # Verify basic fields match | |
| assert restored.classification == result.classification | |
| assert restored.confidence == result.confidence | |
| assert restored.explanation == result.explanation | |
| assert restored.permission_check_message == result.permission_check_message | |
| assert restored.referral_message == result.referral_message | |
| assert restored.consent_status == result.consent_status | |
| assert restored.patient_responses == result.patient_responses | |
| assert restored.re_evaluation_result == result.re_evaluation_result | |
| # Verify nested indicators | |
| assert len(restored.indicators) == len(result.indicators) | |
| for orig, rest in zip(result.indicators, restored.indicators): | |
| assert rest.indicator_text == orig.indicator_text | |
| assert rest.category == orig.category | |
| assert rest.severity == orig.severity | |
| # Verify nested follow-up questions | |
| assert len(restored.follow_up_questions) == len(result.follow_up_questions) | |
| for orig, rest in zip(result.follow_up_questions, restored.follow_up_questions): | |
| assert rest.question_id == orig.question_id | |
| assert rest.question_text == orig.question_text | |
| assert rest.purpose == orig.purpose | |
| class TestTaggingRecordRoundTrip: | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| Tests that TaggingRecord serializes and deserializes correctly. | |
| """ | |
| def test_tagging_record_round_trip(self, record): | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| **Validates: Requirements 8.5** | |
| For any TaggingRecord, converting to dict and back should | |
| preserve all fields exactly. | |
| """ | |
| # Convert to dict and back | |
| record_dict = record.to_dict() | |
| restored = TaggingRecord.from_dict(record_dict) | |
| # Verify all fields match | |
| assert restored.record_id == record.record_id | |
| assert restored.message_id == record.message_id | |
| assert restored.is_classification_correct == record.is_classification_correct | |
| assert restored.classification_subcategory == record.classification_subcategory | |
| assert restored.correct_classification == record.correct_classification | |
| assert restored.question_issues == record.question_issues | |
| assert restored.question_comments == record.question_comments | |
| assert restored.referral_issues == record.referral_issues | |
| assert restored.referral_comments == record.referral_comments | |
| assert restored.indicator_issues == record.indicator_issues | |
| assert restored.indicator_comments == record.indicator_comments | |
| assert restored.general_notes == record.general_notes | |
| class TestInteractionStepLogRoundTrip: | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| Tests that InteractionStepLog serializes and deserializes correctly. | |
| """ | |
| def test_interaction_step_log_round_trip(self, log): | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| **Validates: Requirements 8.5** | |
| For any InteractionStepLog, converting to dict and back should | |
| preserve all fields exactly. | |
| """ | |
| # Convert to dict and back | |
| log_dict = log.to_dict() | |
| restored = InteractionStepLog.from_dict(log_dict) | |
| # Verify all fields match | |
| assert restored.step_id == log.step_id | |
| assert restored.session_id == log.session_id | |
| assert restored.message_id == log.message_id | |
| assert restored.step_type == log.step_type | |
| assert restored.input_text == log.input_text | |
| assert restored.model_output == log.model_output | |
| assert restored.approval_status == log.approval_status | |
| assert restored.tagging_data == log.tagging_data | |
| def test_interaction_step_log_with_tagging_round_trip(self, log): | |
| """ | |
| **Feature: chaplain-feedback-system, Property: Data Model Round Trip** | |
| **Validates: Requirements 8.5** | |
| For any InteractionStepLog with nested TaggingRecord, converting to dict | |
| and back should preserve all fields exactly. | |
| """ | |
| # Convert to dict and back | |
| log_dict = log.to_dict() | |
| restored = InteractionStepLog.from_dict(log_dict) | |
| # Verify basic fields match | |
| assert restored.step_id == log.step_id | |
| assert restored.session_id == log.session_id | |
| assert restored.message_id == log.message_id | |
| assert restored.step_type == log.step_type | |
| assert restored.input_text == log.input_text | |
| assert restored.model_output == log.model_output | |
| assert restored.approval_status == log.approval_status | |
| # Verify nested tagging data | |
| if log.tagging_data is None: | |
| assert restored.tagging_data is None | |
| else: | |
| assert restored.tagging_data is not None | |
| assert restored.tagging_data.record_id == log.tagging_data.record_id | |
| assert restored.tagging_data.message_id == log.tagging_data.message_id | |
| assert restored.tagging_data.is_classification_correct == log.tagging_data.is_classification_correct | |
| assert restored.tagging_data.question_issues == log.tagging_data.question_issues | |
| assert restored.tagging_data.referral_issues == log.tagging_data.referral_issues | |