Skip to content

Commit 611b468

Browse files
committed
feat: select a random value from examples when available
1 parent 1cde4b7 commit 611b468

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

scim2_tester/filling.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,28 @@
2121

2222
from scim2_tester.urns import get_attribute_type_by_urn
2323
from scim2_tester.urns import get_multiplicity_by_urn
24+
from scim2_tester.urns import get_target_model_by_urn
2425
from scim2_tester.urns import iter_all_urns
2526
from scim2_tester.urns import set_value_by_urn
2627

2728
if TYPE_CHECKING:
2829
from scim2_tester.utils import CheckContext
2930

3031

32+
def get_random_example_value(model: type[Resource], urn: str) -> Any | None:
33+
"""Get a random value from pydantic field examples if available."""
34+
target_info = get_target_model_by_urn(model, urn)
35+
if not target_info:
36+
return None
37+
38+
target_model, target_field_name = target_info
39+
field_info = target_model.model_fields.get(target_field_name)
40+
if not field_info or not hasattr(field_info, "examples") or not field_info.examples:
41+
return None
42+
43+
return random.choice(field_info.examples)
44+
45+
3146
def get_model_from_ref_type(
3247
context: "CheckContext", ref_type: type, different_than: type[Resource[Any]] | None
3348
) -> type[Resource[Any]]:
@@ -76,11 +91,14 @@ def generate_random_value(
7691

7792
value: Any
7893

94+
if example_value := get_random_example_value(model, urn):
95+
value = example_value
96+
7997
# RFC7643 §4.1.2 provides the following indications, however
8098
# there is no way to guess the existence of such requirements
8199
# just by looking at the object schema.
82100
# The value SHOULD be specified according to [RFC5321].
83-
if is_email:
101+
elif is_email:
84102
value = f"{uuid.uuid4()}@{uuid.uuid4()}.com"
85103

86104
# RFC7643 §4.1.2 provides the following indications, however

tests/test_filling.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from scim2_tester.filling import fill_with_random_values
1111
from scim2_tester.filling import generate_random_value
1212
from scim2_tester.filling import get_model_from_ref_type
13+
from scim2_tester.filling import get_random_example_value
1314

1415

1516
def test_generate_random_value_bytes_field(testing_context):
@@ -58,3 +59,116 @@ def test_fill_with_nonexistent_field(testing_context):
5859
mock_generate.assert_called_once()
5960

6061
assert result is user
62+
63+
64+
def test_get_random_example_value():
65+
"""Validates random value selection from pydantic field examples."""
66+
from scim2_models import Email
67+
68+
value = get_random_example_value(Email, "type")
69+
70+
assert value in ["work", "home", "other"]
71+
72+
73+
def test_get_random_example_value_no_examples():
74+
"""Returns None when field has no examples."""
75+
from scim2_models import Email
76+
77+
value = get_random_example_value(Email, "value")
78+
79+
assert value is None
80+
81+
82+
def test_get_random_example_value_invalid_urn():
83+
"""Returns None when URN is invalid."""
84+
from scim2_models import Email
85+
86+
value = get_random_example_value(Email, "nonexistent")
87+
88+
assert value is None
89+
90+
91+
def test_generate_random_value_with_examples(testing_context):
92+
"""Uses examples when available."""
93+
from scim2_models import Email
94+
95+
value = generate_random_value(testing_context, "type", Email)
96+
97+
assert value in ["work", "home", "other"]
98+
99+
100+
def test_generate_random_value_phone_number(testing_context):
101+
"""Generates phone numbers correctly."""
102+
from scim2_models import PhoneNumber
103+
104+
value = generate_random_value(testing_context, "phoneNumbers.value", PhoneNumber)
105+
106+
assert isinstance(value, str)
107+
assert len(value) == 10
108+
assert value.isdigit()
109+
110+
111+
def test_generate_random_value_email(testing_context):
112+
"""Generates emails correctly."""
113+
from scim2_models import Email
114+
115+
value = generate_random_value(testing_context, "emails.value", Email)
116+
117+
assert isinstance(value, str)
118+
assert "@" in value
119+
assert value.endswith(".com")
120+
121+
122+
def test_generate_random_value_bool(testing_context):
123+
"""Generates boolean values."""
124+
from scim2_models import User
125+
126+
value = generate_random_value(testing_context, "active", User)
127+
128+
assert isinstance(value, bool)
129+
130+
131+
def test_generate_random_value_int(testing_context):
132+
"""Generates integer values."""
133+
from scim2_models.resources.user import X509Certificate
134+
135+
value = generate_random_value(testing_context, "value", X509Certificate)
136+
137+
assert isinstance(value, str)
138+
139+
140+
def test_generate_random_value_complex_attribute(testing_context):
141+
"""Generates complex attribute values."""
142+
from scim2_models import User
143+
144+
value = generate_random_value(testing_context, "name", User)
145+
146+
assert value is not None
147+
148+
149+
def test_generate_random_value_multiple_field(testing_context):
150+
"""Generates list values for multiple fields."""
151+
from scim2_models import User
152+
153+
value = generate_random_value(testing_context, "emails", User)
154+
155+
assert isinstance(value, list)
156+
157+
158+
def test_generate_random_value_reference_external(testing_context):
159+
"""Generates external reference values."""
160+
from scim2_models import User
161+
162+
value = generate_random_value(testing_context, "profileUrl", User)
163+
164+
assert isinstance(value, str)
165+
assert value.startswith("https://")
166+
167+
168+
def test_generate_random_value_default_string(testing_context):
169+
"""Generates default string values."""
170+
from scim2_models import User
171+
172+
value = generate_random_value(testing_context, "title", User)
173+
174+
assert isinstance(value, str)

0 commit comments

Comments
 (0)