Skip to content

Commit 2faeee5

Browse files
Евгений БлиновЕвгений Блинов
authored andcommitted
Make some tests stronger
1 parent 3147f94 commit 2faeee5

2 files changed

Lines changed: 45 additions & 12 deletions

File tree

‎tests/units/test_check.py‎

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def test_built_in_types():
6363

6464

6565
def test_any():
66-
"""typing.Any matches all sampled values, including primitives, collections, None, and type objects."""
66+
"""typing.Any matches all sampled values, including primitives, collections, None, and type objects, even in strict mode."""
6767
assert check(True, Any)
6868
assert check(False, Any)
6969
assert check(0, Any)
@@ -76,6 +76,10 @@ def test_any():
7676
assert check(None, Any)
7777
assert check(str, Any)
7878
assert check(-1000, Any)
79+
assert check([1, 'two', None], Any, strict=True)
80+
assert check((1, 'two', None), Any, strict=True)
81+
assert check(str, Any, strict=True)
82+
assert check(None, Any, strict=True)
7983

8084

8185
@pytest.mark.skipif(sys.version_info > (3, 13), reason="Before Python 3.14, you couldn't just use Union as an annotation.")
@@ -192,6 +196,23 @@ def test_optional(tuple_type, list_type, make_optional):
192196
assert check((1, 2, 3), make_optional(tuple_type))
193197

194198

199+
def test_optional_with_parameterized_collections_in_strict_mode(make_optional, subscribable_list_type, subscribable_tuple_type):
200+
"""
201+
Strict Optional checks pass strict validation through to parameterized collections.
202+
203+
None still matches, but present list and tuple values must satisfy their inner annotations.
204+
"""
205+
assert check(None, make_optional(subscribable_list_type[int]), strict=True)
206+
assert check([1, 2, 3], make_optional(subscribable_list_type[int]), strict=True)
207+
assert not check(['1', '2', '3'], make_optional(subscribable_list_type[int]), strict=True)
208+
assert not check((1, 2, 3), make_optional(subscribable_list_type[int]), strict=True)
209+
210+
assert check(None, make_optional(subscribable_tuple_type[int, str]), strict=True)
211+
assert check((1, 'kek'), make_optional(subscribable_tuple_type[int, str]), strict=True)
212+
assert not check((1, 2), make_optional(subscribable_tuple_type[int, str]), strict=True)
213+
assert not check([1, 'kek'], make_optional(subscribable_tuple_type[int, str]), strict=True)
214+
215+
195216
def test_optional_union(make_union, make_optional, tuple_type):
196217
"""
197218
Optional unions accept None or any inner union member across typing and PEP 604 spellings.
@@ -342,12 +363,15 @@ def test_dict_without_arguments(dict_type, addictional_parameters):
342363

343364

344365
def test_content_of_list_not_in_strict_mode_is_not_checking(subscribable_list_type):
345-
"""Non-strict List[int]/list[int] checks accept any list regardless of element contents."""
366+
"""Non-strict List[int]/list[int] checks accept any list regardless of element contents, but still reject non-lists."""
346367
assert check([], subscribable_list_type[int])
347368
assert check(['lol', 'kek'], subscribable_list_type[int])
348369
assert check([1.0, 2.0], subscribable_list_type[int])
349370
assert check([None, None], subscribable_list_type[int])
350371
assert check([None, 'kek', 1, 1.0], subscribable_list_type[int])
372+
assert not check((), subscribable_list_type[int])
373+
assert not check((1, 2, 3), subscribable_list_type[int])
374+
assert not check('kek', subscribable_list_type[int])
351375

352376

353377
def test_content_of_tuple_not_in_strict_mode_is_not_checking(subscribable_tuple_type):
@@ -360,23 +384,29 @@ def test_content_of_tuple_not_in_strict_mode_is_not_checking(subscribable_tuple_
360384

361385

362386
def test_content_of_dict_not_in_strict_mode_is_not_checking(subscribable_dict_type):
363-
"""Non-strict Dict[int, int]/dict[int, int] validation accepts any dict regardless of key and value types."""
387+
"""Non-strict Dict[int, int]/dict[int, int] validation accepts any dict regardless of contents, but still rejects non-dicts."""
364388
assert check({}, subscribable_dict_type[int, int])
365389
assert check({1: 'kek'}, subscribable_dict_type[int, int])
366390
assert check({'lol': 'kek'}, subscribable_dict_type[int, int])
367391
assert check({'lol': 1}, subscribable_dict_type[int, int])
368392
assert check({1.0: 1}, subscribable_dict_type[int, int])
393+
assert not check([], subscribable_dict_type[int, int])
394+
assert not check([(1, 2)], subscribable_dict_type[int, int])
395+
assert not check('{1: 1}', subscribable_dict_type[int, int])
369396

370397

371398
@pytest.mark.skipif(sys.version_info < (3, 9), reason='Subscribing to objects became available in Python 3.9')
372399
def test_content_of_set_not_in_strict_mode_is_not_checking():
373-
"""Non-strict set[int] validation checks only the set origin and ignores element types."""
400+
"""Non-strict set[int] validation accepts any set regardless of element contents, but still rejects non-sets."""
374401
assert check(set(), set[int])
375402
assert check(set(['lol', 'kek']), set[int])
376403
assert check(set([1, 'kek']), set[int])
377404
assert check(set([1, None]), set[int])
378405
assert check(set([None, None]), set[int])
379406
assert check(set(['1', '2']), set[int])
407+
assert not check([], set[int])
408+
assert not check(('1', '2'), set[int])
409+
assert not check('kek', set[int])
380410

381411

382412
def test_try_to_pass_not_type_object_as_type():
@@ -415,9 +445,10 @@ def test_sequence():
415445

416446
@pytest.mark.skipif(sys.version_info < (3, 9), reason='Subscribing to objects became available in Python 3.9')
417447
def test_sequence_is_not_checking_content():
418-
"""Sequence[str] checks only the sequence origin, so integer lists and tuples still pass."""
448+
"""Sequence[str] checks only the sequence origin, so integer lists and tuples pass while non-sequence containers fail."""
419449
assert check((1, 2, 3), Sequence[str])
420450
assert check([1, 2, 3], Sequence[str])
451+
assert not check({1, 2, 3}, Sequence[str])
421452

422453

423454
def test_list_with_values_in_strict_mode(subscribable_list_type, make_union):
@@ -569,6 +600,8 @@ def test_pass_mocks_when_its_off(strict_mode, list_type):
569600
assert not check(MagicMock(), list_type, strict=strict_mode, pass_mocks=False)
570601

571602
assert check(Mock(), Mock, strict=strict_mode, pass_mocks=False)
603+
assert check(MagicMock(), Mock, strict=strict_mode, pass_mocks=False)
604+
assert not check(Mock(), MagicMock, strict=strict_mode, pass_mocks=False)
572605
assert check(MagicMock(), MagicMock, strict=strict_mode, pass_mocks=False)
573606

574607

‎tests/units/test_from_string.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,17 @@ def test_get_float_value():
124124

125125
def test_get_bool_value():
126126
"""
127-
Boolean deserialization accepts only the exact string tokens "yes", "True", "true", "False", "false", and "no".
127+
Boolean deserialization returns True/False singletons only for the exact accepted string tokens.
128128
129129
Empty, unknown, or near-match strings raise the boolean-specific TypeError.
130130
"""
131-
assert from_string('yes', bool) == True
132-
assert from_string('True', bool) == True
133-
assert from_string('true', bool) == True
131+
assert from_string('yes', bool) is True
132+
assert from_string('True', bool) is True
133+
assert from_string('true', bool) is True
134134

135-
assert from_string('False', bool) == False
136-
assert from_string('false', bool) == False
137-
assert from_string('no', bool) == False
135+
assert from_string('False', bool) is False
136+
assert from_string('false', bool) is False
137+
assert from_string('no', bool) is False
138138

139139
with pytest.raises(TypeError, match=match('The string "kek" cannot be interpreted as a boolean value.')):
140140
from_string('kek', bool)

0 commit comments

Comments
 (0)