File size: 5,292 Bytes
ab93d81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# conftest.py
"""
Pytest fixtures for Chaplain Feedback tests.
"""

import pytest
from hypothesis import strategies as st
from datetime import datetime

from src.core.chaplain_models import (
    DistressIndicator,
    FollowUpQuestion,
    ClassificationFlowResult,
    TaggingRecord,
    InteractionStepLog,
    INDICATOR_DEFINITIONS,
    CLASSIFICATION_SUBCATEGORIES,
    QUESTION_ISSUE_TYPES,
    REFERRAL_ISSUE_TYPES,
    INTERACTION_STEP_TYPES,
)


# =============================================================================
# Hypothesis Strategies for generating test data
# =============================================================================

def valid_id_strategy():
    """Generate valid IDs."""
    return st.text(
        alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-",
        min_size=1,
        max_size=20,
    )


def distress_indicator_strategy():
    """Generate random DistressIndicator instances."""
    return st.builds(
        DistressIndicator,
        indicator_text=st.text(min_size=1, max_size=200),
        category=st.sampled_from([
            "Emotional", "Grief", "Existential", "Expressions", 
            "Spiritual", "Medical", "Social", "Cultural", 
            "Engagement", "Guilt", "Anger", "Aging", 
            "Environment", "Independence"
        ]),
        subcategory=st.text(min_size=1, max_size=100),
        severity=st.sampled_from(["red", "yellow"]),
        confidence=st.floats(min_value=0.0, max_value=1.0, allow_nan=False),
        definition_reference=st.text(max_size=20),
    )


def follow_up_question_strategy():
    """Generate random FollowUpQuestion instances."""
    return st.builds(
        FollowUpQuestion,
        question_id=valid_id_strategy(),
        question_text=st.text(min_size=1, max_size=500),
        purpose=st.text(min_size=1, max_size=200),
    )


def classification_flow_result_strategy():
    """Generate random ClassificationFlowResult instances."""
    return st.builds(
        ClassificationFlowResult,
        classification=st.sampled_from(["red", "yellow", "green"]),
        confidence=st.floats(min_value=0.0, max_value=1.0, allow_nan=False),
        indicators=st.lists(distress_indicator_strategy(), max_size=5),
        explanation=st.text(max_size=500),
        permission_check_message=st.one_of(st.none(), st.text(max_size=300)),
        referral_message=st.one_of(st.none(), st.text(max_size=500)),
        consent_status=st.one_of(st.none(), st.sampled_from(["granted", "declined"])),
        follow_up_questions=st.lists(follow_up_question_strategy(), max_size=3),
        patient_responses=st.lists(st.text(max_size=200), max_size=3),
        re_evaluation_result=st.one_of(st.none(), st.sampled_from(["red", "green"])),
    )


def tagging_record_strategy():
    """Generate random TaggingRecord instances."""
    return st.builds(
        TaggingRecord,
        record_id=valid_id_strategy(),
        message_id=valid_id_strategy(),
        is_classification_correct=st.booleans(),
        classification_subcategory=st.one_of(
            st.none(), 
            st.sampled_from(CLASSIFICATION_SUBCATEGORIES)
        ),
        correct_classification=st.one_of(
            st.none(), 
            st.sampled_from(["red", "yellow", "green"])
        ),
        question_issues=st.lists(
            st.sampled_from(QUESTION_ISSUE_TYPES), 
            max_size=3, 
            unique=True
        ),
        question_comments=st.one_of(st.none(), st.text(max_size=200)),
        referral_issues=st.lists(
            st.sampled_from(REFERRAL_ISSUE_TYPES), 
            max_size=3, 
            unique=True
        ),
        referral_comments=st.one_of(st.none(), st.text(max_size=200)),
        indicator_issues=st.lists(st.text(min_size=1, max_size=50), max_size=5),
        indicator_comments=st.one_of(st.none(), st.text(max_size=200)),
        general_notes=st.text(max_size=300),
        timestamp=st.just(datetime.now()),
    )


def interaction_step_log_strategy():
    """Generate random InteractionStepLog instances (without nested tagging)."""
    return st.builds(
        InteractionStepLog,
        step_id=valid_id_strategy(),
        session_id=valid_id_strategy(),
        message_id=valid_id_strategy(),
        step_type=st.sampled_from(INTERACTION_STEP_TYPES),
        input_text=st.text(max_size=500),
        model_output=st.text(max_size=500),
        approval_status=st.one_of(st.none(), st.sampled_from(["approved", "disapproved"])),
        tagging_data=st.none(),  # Simplified - no nested tagging for basic tests
        timestamp=st.just(datetime.now()),
    )


def interaction_step_log_with_tagging_strategy():
    """Generate random InteractionStepLog instances with nested tagging."""
    return st.builds(
        InteractionStepLog,
        step_id=valid_id_strategy(),
        session_id=valid_id_strategy(),
        message_id=valid_id_strategy(),
        step_type=st.sampled_from(INTERACTION_STEP_TYPES),
        input_text=st.text(max_size=500),
        model_output=st.text(max_size=500),
        approval_status=st.one_of(st.none(), st.sampled_from(["approved", "disapproved"])),
        tagging_data=st.one_of(st.none(), tagging_record_strategy()),
        timestamp=st.just(datetime.now()),
    )