diff options
author | Seth M Morton <seth.m.morton@gmail.com> | 2018-01-27 19:55:54 -0800 |
---|---|---|
committer | Seth M Morton <seth.m.morton@gmail.com> | 2018-01-27 20:02:16 -0800 |
commit | 1b3b26828dd751d8f60cb8b41cd66ed19ba26cf9 (patch) | |
tree | 6d1cde39e1f14ff6800da9110a0b88dbcf806dbe | |
parent | 9a5901b4d6e97ee7834974b22744af26372def75 (diff) | |
download | natsort-1b3b26828dd751d8f60cb8b41cd66ed19ba26cf9.tar.gz |
Update hypothesis tests to not rely on "assume".
Rather than generating testing values and then removing them in
post-processing, now test values are created correct-by-construction
using the newer .filter API of hypothesis strategies.
Whilst doing this filtering, it was found that the range_check
function was doing the unnecessary step of converting its input to
floats, so this has been removed (which simplifies testing).
Last, some of the tests for the command-line --filter arguments have
been simplified because the ROI of the thorough hypothesis tests
was low.
-rw-r--r-- | natsort/__main__.py | 5 | ||||
-rw-r--r-- | test_natsort/test_fake_fastnumbers.py | 48 | ||||
-rw-r--r-- | test_natsort/test_final_data_transform_factory.py | 12 | ||||
-rw-r--r-- | test_natsort/test_main.py | 87 | ||||
-rw-r--r-- | test_natsort/test_natsort_key.py | 11 | ||||
-rw-r--r-- | test_natsort/test_parse_number_function.py | 14 | ||||
-rw-r--r-- | test_natsort/test_parse_string_function.py | 24 | ||||
-rw-r--r-- | test_natsort/test_string_component_transform_factory.py | 27 | ||||
-rw-r--r-- | test_natsort/test_utils.py | 13 |
9 files changed, 81 insertions, 160 deletions
diff --git a/natsort/__main__.py b/natsort/__main__.py index 5361ea2..f2b4e29 100644 --- a/natsort/__main__.py +++ b/natsort/__main__.py @@ -103,9 +103,8 @@ def range_check(low, high): """\ Verifies that that given range has a low lower than the high. If the condition is not met, a ValueError is raised. - Otherwise, the values are returned, but as floats. + Otherwise the input is returned as-is. """ - low, high = float(low), float(high) if low >= high: raise ValueError('low >= high') else: @@ -117,7 +116,7 @@ def check_filter(filt): Check that the low value of the filter is lower than the high. If there is to be no filter, return 'None'. If the condition is not met, a ValueError is raised. - Otherwise, the values are returned, but as floats. + Otherwise, the values are returned as-is. """ # Quick return if no filter. if not filt: diff --git a/test_natsort/test_fake_fastnumbers.py b/test_natsort/test_fake_fastnumbers.py index 1ac05f8..c9103c2 100644 --- a/test_natsort/test_fake_fastnumbers.py +++ b/test_natsort/test_fake_fastnumbers.py @@ -12,7 +12,6 @@ from natsort.compat.fake_fastnumbers import ( fast_int, ) from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( @@ -39,18 +38,29 @@ def is_float(x): return True +def not_a_float(x): + return not is_float(x) + + def is_int(x): try: - long(x) - except ValueError: + return x.is_integer() + except AttributeError: try: - unicodedata.digit(x) - except (ValueError, TypeError): - return False + long(x) + except ValueError: + try: + unicodedata.digit(x) + except (ValueError, TypeError): + return False + else: + return True else: return True - else: - return True + + +def not_an_int(x): + return not is_int(x) # Each test has an "example" version for demonstrative purposes, @@ -70,9 +80,8 @@ def test_fast_float_converts_float_string_to_float_example(): assert isnan(fast_float('-NaN')) -@given(floats()) +@given(floats(allow_nan=False)) def test_fast_float_converts_float_string_to_float(x): - assume(not isnan(x)) # But inf is included assert fast_float(repr(x)) == x @@ -80,10 +89,8 @@ def test_fast_float_leaves_string_as_is_example(): assert fast_float('invalid') == 'invalid' -@given(text()) +@given(text().filter(not_a_float).filter(bool)) def test_fast_float_leaves_string_as_is(x): - assume(not is_float(x)) - assume(bool(x)) assert fast_float(x) == x @@ -91,10 +98,8 @@ def test_fast_float_with_key_applies_to_string_example(): assert fast_float('invalid', key=len) == len('invalid') -@given(text()) +@given(text().filter(not_a_float).filter(bool)) def test_fast_float_with_key_applies_to_string(x): - assume(not is_float(x)) - assume(bool(x)) assert fast_float(x, key=len) == len(x) @@ -104,9 +109,8 @@ def test_fast_int_leaves_float_string_as_is_example(): assert fast_int('inf') == 'inf' -@given(floats()) +@given(floats().filter(not_an_int)) def test_fast_int_leaves_float_string_as_is(x): - assume(not x.is_integer()) assert fast_int(repr(x)) == repr(x) @@ -124,10 +128,8 @@ def test_fast_int_leaves_string_as_is_example(): assert fast_int('invalid') == 'invalid' -@given(text()) +@given(text().filter(not_an_int).filter(bool)) def test_fast_int_leaves_string_as_is(x): - assume(not is_int(x)) - assume(bool(x)) assert fast_int(x) == x @@ -135,8 +137,6 @@ def test_fast_int_with_key_applies_to_string_example(): assert fast_int('invalid', key=len) == len('invalid') -@given(text()) +@given(text().filter(not_an_int).filter(bool)) def test_fast_int_with_key_applies_to_string(x): - assume(not is_int(x)) - assume(bool(x)) assert fast_int(x, key=len) == len(x) diff --git a/test_natsort/test_final_data_transform_factory.py b/test_natsort/test_final_data_transform_factory.py index 95baedd..bfd3dfd 100644 --- a/test_natsort/test_final_data_transform_factory.py +++ b/test_natsort/test_final_data_transform_factory.py @@ -2,12 +2,10 @@ """These test the utils.py functions.""" from __future__ import unicode_literals -from math import isnan, isinf from natsort.ns_enum import ns from natsort.utils import _final_data_transform_factory from natsort.compat.py23 import py23_str from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( @@ -45,11 +43,8 @@ def test_final_data_transform_factory_returns_first_element_in_first_tuple_eleme assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '')(('this', 60), 'this60') == (('t',), ('this', 60)) -@given(x=text(), y=floats() | integers()) +@given(x=text().filter(bool), y=floats(allow_nan=False, allow_infinity=False) | integers()) def test_final_data_transform_factory_returns_first_element_in_first_tuple_element(x, y): - assume(x) - assume(not isnan(y)) - assume(not isinf(y)) assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0],), (x, y)) @@ -57,9 +52,6 @@ def test_final_data_transform_factory_returns_first_element_in_first_tuple_eleme assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')(('this', 60), 'this60') == (('T',), ('this', 60)) -@given(x=text(), y=floats() | integers()) +@given(x=text().filter(bool), y=floats(allow_nan=False, allow_infinity=False) | integers()) def test_final_data_transform_factory_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST(x, y): - assume(x) - assume(not isnan(y)) - assume(not isinf(y)) assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0].swapcase(),), (x, y)) diff --git a/test_natsort/test_main.py b/test_natsort/test_main.py index 704e0bb..6455c69 100644 --- a/test_natsort/test_main.py +++ b/test_natsort/test_main.py @@ -8,15 +8,13 @@ import sys from pytest import raises from compat.mock import patch, call from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( - sampled_from, integers, floats, - tuples, - text, + lists, + data, ) from natsort.__main__ import ( main, @@ -25,7 +23,6 @@ from natsort.__main__ import ( keep_entry_range, exclude_entry, sort_and_print_entries, - py23_str, ) @@ -173,15 +170,17 @@ def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_s assert range_check(6.4, 30) == (6.4, 30.0) -@given(x=integers(), y=integers()) -def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_second(x, y): - assume(float(x) < float(y)) - assert range_check(x, y) == (float(x), float(y)) +@given(x=integers(), data=data()) # Defer data selection for y till test is run. +def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_second(x, data): + # Pull data such that the first is less than the second. + y = data.draw(integers(min_value=x + 1)) + assert range_check(x, y) == (x, y) -@given(x=floats(), y=floats()) -def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_second2(x, y): - assume(x < y) +@given(x=floats(allow_nan=False, min_value=-1E8, max_value=1E8), data=data()) # Defer data selection for y till test is run. +def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_second2(x, data): + # Pull data such that the first is less than the second. + y = data.draw(floats(min_value=x + 1.0, max_value=1E9, allow_nan=False)) assert range_check(x, y) == (x, y) @@ -191,11 +190,12 @@ def test_range_check_raises_ValueError_if_second_is_less_than_first_example(): assert str(err.value) == 'low >= high' -@given(x=floats(), y=floats()) -def test_range_check_raises_ValueError_if_second_is_less_than_first(x, y): - assume(x >= y) +@given(x=floats(allow_nan=False), data=data()) # Defer data selection for y till test is run. +def test_range_check_raises_ValueError_if_second_is_less_than_first(x, data): + # Pull data such that the first is greater than or equal to the second. + y = data.draw(floats(max_value=x, allow_nan=False)) with raises(ValueError) as err: - range_check(x, x) + range_check(x, y) assert str(err.value) == 'low >= high' @@ -205,15 +205,15 @@ def test_check_filter_returns_None_if_filter_evaluates_to_False(): assert check_filter(None) is None -def test_check_filter_converts_filter_numbers_to_floats_if_filter_is_valid_example(): - assert check_filter([(6, 7)]) == [(6.0, 7.0)] - assert check_filter([(6, 7), (2, 8)]) == [(6.0, 7.0), (2.0, 8.0)] +def test_check_filter_returns_input_as_is_if_filter_is_valid_example(): + assert check_filter([(6, 7)]) == [(6, 7)] + assert check_filter([(6, 7), (2, 8)]) == [(6, 7), (2, 8)] -@given(x=tuples(integers(), integers(), floats(), floats()), y=tuples(integers(), floats(), floats(), integers())) -def test_check_filter_converts_filter_numbers_to_floats_if_filter_is_valid(x, y): - assume(all(float(i) < float(j) for i, j in zip(x, y))) - assert check_filter(list(zip(x, y))) == [(float(i), float(j)) for i, j in zip(x, y)] +@given(x=lists(integers(), min_size=1), data=data()) # Defer data selection for y till test is run. +def test_check_filter_returns_input_as_is_if_filter_is_valid(x, data): + y = [data.draw(integers(min_value=val + 1)) for val in x] # ensure y is element-wise greater than x + assert check_filter(list(zip(x, y))) == [(i, j) for i, j in zip(x, y)] def test_check_filter_raises_ValueError_if_filter_is_invalid_example(): @@ -222,9 +222,9 @@ def test_check_filter_raises_ValueError_if_filter_is_invalid_example(): assert str(err.value) == 'Error in --filter: low >= high' -@given(x=tuples(integers(), integers(), floats(), floats()), y=tuples(integers(), floats(), floats(), integers())) -def test_check_filter_raises_ValueError_if_filter_is_invalid(x, y): - assume(any(float(i) >= float(j) for i, j in zip(x, y))) +@given(x=lists(integers(), min_size=1), data=data()) # Defer data selection for y till test is run. +def test_check_filter_raises_ValueError_if_filter_is_invalid(x, data): + y = [data.draw(integers(max_value=val)) for val in x] # ensure y is element-wise less than or equal to x with raises(ValueError) as err: check_filter(list(zip(x, y))) assert str(err.value) == 'Error in --filter: low >= high' @@ -234,52 +234,17 @@ def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_the_ra assert keep_entry_range('a56b23c89', [0], [100], int, re.compile(r'\d+')) -@given(tuples(text(), integers(1, 99), text(), integers(1, 99), text())) -def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_the_range_bounds(x): - s = ''.join(map(py23_str, x)) - assume(any(0 < int(i) < 100 for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) - assert keep_entry_range(s, [0], [100], int, re.compile(r'\d+')) - - def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_any_range_bounds_example(): assert keep_entry_range('a56b23c89', [1, 88], [20, 90], int, re.compile(r'\d+')) -@given(tuples(text(), integers(2, 89), text(), integers(2, 89), text())) -def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_any_range_bounds(x): - s = ''.join(map(py23_str, x)) - assume(any((1 < int(i) < 20) or (88 < int(i) < 90) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) - assert keep_entry_range(s, [1, 88], [20, 90], int, re.compile(r'\d+')) - - def test_keep_entry_range_returns_False_if_no_portion_of_input_is_between_the_range_bounds_example(): assert not keep_entry_range('a56b23c89', [1], [20], int, re.compile(r'\d+')) -@given(tuples(text(), integers(min_value=21), text(), integers(min_value=21), text())) -def test_keep_entry_range_returns_False_if_no_portion_of_input_is_between_the_range_bounds(x): - s = ''.join(map(py23_str, x)) - assume(all(not (1 <= int(i) <= 20) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) - assert not keep_entry_range(s, [1], [20], int, re.compile(r'\d+')) - - def test_exclude_entry_returns_True_if_exlcude_parameters_are_not_in_input_example(): assert exclude_entry('a56b23c89', [100, 45], int, re.compile(r'\d+')) -@given(tuples(text(), integers(min_value=0), text(), integers(min_value=0), text())) -def test_exclude_entry_returns_True_if_exlcude_parameters_are_not_in_input(x): - s = ''.join(map(py23_str, x)) - assume(not any(int(i) in (23, 45, 87) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) - assert exclude_entry(s, [23, 45, 87], int, re.compile(r'\d+')) - - def test_exclude_entry_returns_False_if_exlcude_parameters_are_in_input_example(): assert not exclude_entry('a56b23c89', [23], int, re.compile(r'\d+')) - - -@given(tuples(text(), sampled_from([23, 45, 87]), text(), sampled_from([23, 45, 87]), text())) -def test_exclude_entry_returns_False_if_exlcude_parameters_are_in_input(x): - s = ''.join(map(py23_str, x)) - assume(any(int(i) in (23, 45, 87) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) - assert not exclude_entry(s, [23, 45, 87], int, re.compile(r'\d+')) diff --git a/test_natsort/test_natsort_key.py b/test_natsort/test_natsort_key.py index e442f48..a675cb2 100644 --- a/test_natsort/test_natsort_key.py +++ b/test_natsort/test_natsort_key.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import pytest -from math import isnan from natsort.compat.py23 import PY_VERSION from natsort.ns_enum import ns from natsort.utils import ( @@ -18,7 +17,6 @@ from natsort.utils import ( _final_data_transform_factory, ) from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( @@ -73,22 +71,19 @@ def test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple() # They only confirm that _natsort_key uses the above building blocks. -@given(floats() | integers()) +@given(floats(allow_nan=False) | integers()) def test__natsort_key_with_numeric_input_takes_number_path(x): - assume(not isnan(x)) assert _natsort_key(x, None, string_func, bytes_func, num_func) == num_func(x) @pytest.mark.skipif(PY_VERSION < 3, reason='only valid on python3') -@given(binary()) +@given(binary().filter(bool)) def test__natsort_key_with_bytes_input_takes_bytes_path(x): - assume(x) assert _natsort_key(x, None, string_func, bytes_func, num_func) == bytes_func(x) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats(allow_nan=False) | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_text_input_takes_string_path(x): - assume(not any(type(y) == float and isnan(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _natsort_key(s, None, string_func, bytes_func, num_func) == string_func(s) diff --git a/test_natsort/test_parse_number_function.py b/test_natsort/test_parse_number_function.py index 541a914..163d066 100644 --- a/test_natsort/test_parse_number_function.py +++ b/test_natsort/test_parse_number_function.py @@ -2,11 +2,9 @@ """These test the utils.py functions.""" from __future__ import unicode_literals -from math import isnan from natsort.ns_enum import ns from natsort.utils import _parse_number_factory from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( @@ -25,9 +23,8 @@ def test_parse_number_factory_makes_function_that_returns_tuple_example(): assert _parse_number_factory(ns.NANLAST, '')(float('nan')) == ('', float('+inf')) -@given(floats() | integers()) +@given(floats(allow_nan=False) | integers()) def test_parse_number_factory_makes_function_that_returns_tuple(x): - assume(not isnan(x)) assert _parse_number_factory(0, '')(x) == ('', x) @@ -35,9 +32,8 @@ def test_parse_number_factory_with_PATH_makes_function_that_returns_nested_tuple assert _parse_number_factory(ns.PATH, '')(57) == (('', 57),) -@given(floats() | integers()) +@given(floats(allow_nan=False) | integers()) def test_parse_number_factory_with_PATH_makes_function_that_returns_nested_tuple(x): - assume(not isnan(x)) assert _parse_number_factory(ns.PATH, '')(x) == (('', x),) @@ -45,9 +41,8 @@ def test_parse_number_factory_with_UNGROUPLETTERS_LOCALE_makes_function_that_ret assert _parse_number_factory(ns.UNGROUPLETTERS | ns.LOCALE, '')(57) == (('',), ('', 57)) -@given(floats() | integers()) +@given(floats(allow_nan=False) | integers()) def test_parse_number_factory_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple(x): - assume(not isnan(x)) assert _parse_number_factory(ns.UNGROUPLETTERS | ns.LOCALE, '')(x) == (('',), ('', x)) @@ -55,7 +50,6 @@ def test_parse_number_factory_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_tha assert _parse_number_factory(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '')(57) == ((('',), ('', 57)),) -@given(floats() | integers()) +@given(floats(allow_nan=False) | integers()) def test_parse_number_factory_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple(x): - assume(not isnan(x)) assert _parse_number_factory(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '')(x) == ((('',), ('', x)),) diff --git a/test_natsort/test_parse_string_function.py b/test_natsort/test_parse_string_function.py index 0dceabd..91dcf08 100644 --- a/test_natsort/test_parse_string_function.py +++ b/test_natsort/test_parse_string_function.py @@ -2,7 +2,6 @@ """These test the utils.py functions.""" from __future__ import unicode_literals -from math import isnan from pytest import raises from natsort.ns_enum import ns from natsort.utils import ( @@ -25,7 +24,6 @@ from slow_splitters import ( float_splitter, ) from hypothesis import ( - assume, given, example, ) @@ -80,12 +78,11 @@ def test_parse_string_factory_only_parses_digits_with_nosign_int_example(): assert _parse_string_factory(0, '', _int_nosign_re.split, no_op, fast_int, tuple2)('a5+5.034e-1') == ('a', 5, '+', 5, '.', 34, 'e-', 1) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats() | text().filter(whitespace_check) | integers(), min_size=1, max_size=10)) @example([10000000000000000000000000000000000000000000000000000000000000000000000000, 100000000000000000000000000000000000000000000000000000000000000000000000000, 100000000000000000000000000000000000000000000000000000000000000000000000000]) def test_parse_string_factory_only_parses_digits_with_nosign_int(x): - assume(all(whitespace_check(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _parse_string_factory(0, '', _int_nosign_re.split, no_op, fast_int, tuple2)(s) == int_splitter(s, False, '') @@ -94,9 +91,8 @@ def test_parse_string_factory_parses_digit_with_sign_with_signed_int_example(): assert _parse_string_factory(0, '', _int_sign_re.split, no_op, fast_int, tuple2)('a5+5.034e-1') == ('a', 5, '', 5, '.', 34, 'e', -1) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats() | text().filter(whitespace_check) | integers(), min_size=1, max_size=10)) def test_parse_string_factory_parses_digit_with_sign_with_signed_int(x): - assume(all(whitespace_check(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _parse_string_factory(0, '', _int_sign_re.split, no_op, fast_int, tuple2)(s) == int_splitter(s, True, '') @@ -105,10 +101,8 @@ def test_parse_string_factory_only_parses_float_with_nosign_noexp_float_example( assert _parse_string_factory(0, '', _float_nosign_noexp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '+', 5.034, 'e-', 1.0) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats(allow_nan=False) | text().filter(whitespace_check) | integers(), min_size=1, max_size=10)) def test_parse_string_factory_only_parses_float_with_nosign_noexp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _parse_string_factory(0, '', _float_nosign_noexp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, False, False, '') @@ -117,10 +111,8 @@ def test_parse_string_factory_only_parses_float_with_exponent_with_nosign_exp_fl assert _parse_string_factory(0, '', _float_nosign_exp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '+', 0.5034) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats(allow_nan=False) | text().filter(whitespace_check) | integers(), min_size=1, max_size=10)) def test_parse_string_factory_only_parses_float_with_exponent_with_nosign_exp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _parse_string_factory(0, '', _float_nosign_exp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, False, True, '') @@ -129,10 +121,8 @@ def test_parse_string_factory_only_parses_float_with_sign_with_sign_noexp_float_ assert _parse_string_factory(0, '', _float_sign_noexp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '', 5.034, 'e', -1.0) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats(allow_nan=False) | text().filter(whitespace_check) | integers(), min_size=1, max_size=10)) def test_parse_string_factory_only_parses_float_with_sign_with_sign_noexp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _parse_string_factory(0, '', _float_sign_noexp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, True, False, '') @@ -142,10 +132,8 @@ def test_parse_string_factory_parses_float_with_sign_exp_float_example(): assert _parse_string_factory(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)('6a5+5.034e-1') == ('', 6.0, 'a', 5.0, '', 0.5034) -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@given(lists(elements=floats(allow_nan=False) | text().filter(whitespace_check) | integers(), min_size=1, max_size=10)) def test_parse_string_factory_parses_float_with_sign_exp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _parse_string_factory(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, True, True, '') diff --git a/test_natsort/test_string_component_transform_factory.py b/test_natsort/test_string_component_transform_factory.py index 46d9f6b..4f419d7 100644 --- a/test_natsort/test_string_component_transform_factory.py +++ b/test_natsort/test_string_component_transform_factory.py @@ -14,7 +14,6 @@ from natsort.compat.fastnumbers import ( fast_int, ) from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( @@ -25,6 +24,10 @@ from hypothesis.strategies import ( from compat.locale import bad_uni_chars +def no_null(x): + return '\0' not in x + + # Each test has an "example" version for demonstrative purposes, # and a test that uses the hypothesis module. @@ -35,9 +38,8 @@ def test_string_component_transform_factory_returns_fast_int_example(): assert _string_component_transform_factory(0)('5007') == fast_int('5007') -@given(text() | floats() | integers()) +@given(text().filter(bool) | floats() | integers()) def test_string_component_transform_factory_returns_fast_int(x): - assume(x) assert _string_component_transform_factory(0)(py23_str(x)) == fast_int(py23_str(x)) @@ -47,9 +49,8 @@ def test_string_component_transform_factory_with_FLOAT_returns_fast_float_exampl assert _string_component_transform_factory(ns.FLOAT)('5007') == fast_float('5007') -@given(text() | floats() | integers()) +@given(text().filter(bool) | floats() | integers()) def test_string_component_transform_factory_with_FLOAT_returns_fast_float(x): - assume(x) assert _string_component_transform_factory(ns.FLOAT)(py23_str(x)) == fast_float(py23_str(x), nan=float('-inf')) @@ -66,9 +67,8 @@ def test_string_component_transform_factory_with_GROUPLETTERS_returns_fast_int_a assert _string_component_transform_factory(ns.GROUPLETTERS)(x) == fast_int(x, key=_groupletters) -@given(text()) +@given(text().filter(bool)) def test_string_component_transform_factory_with_GROUPLETTERS_returns_fast_int_and_groupletters(x): - assume(x) assert _string_component_transform_factory(ns.GROUPLETTERS)(x) == fast_int(x, key=_groupletters) @@ -77,11 +77,8 @@ def test_string_component_transform_factory_with_LOCALE_returns_fast_int_and_gro assert _string_component_transform_factory(ns.LOCALE)(x) == fast_int(x, key=get_strxfrm()) -@given(text()) +@given(text().filter(bool).filter(lambda x: not any(y in bad_uni_chars for y in x)).filter(no_null)) def test_string_component_transform_factory_with_LOCALE_returns_fast_int_and_groupletters(x): - assume(x) - assume(not any(y in bad_uni_chars for y in x)) - assume('\0' not in x) assert _string_component_transform_factory(ns.LOCALE)(x) == fast_int(x, key=get_strxfrm()) @@ -90,10 +87,8 @@ def test_string_component_transform_factory_with_LOCALE_and_GROUPLETTERS_returns assert _string_component_transform_factory(ns.GROUPLETTERS | ns.LOCALE)(x) == fast_int(x, key=lambda x: get_strxfrm()(_groupletters(x))) -@given(text()) +@given(text().filter(bool).filter(no_null)) def test_string_component_transform_factory_with_LOCALE_and_GROUPLETTERS_returns_fast_int_and_groupletters_and_locale_convert(x): - assume(x) - assume('\0' not in x) try: assert _string_component_transform_factory(ns.GROUPLETTERS | ns.LOCALE)(x) == fast_int(x, key=lambda x: get_strxfrm()(_groupletters(x))) except ValueError as e: # handle broken locale lib on BSD. @@ -106,10 +101,8 @@ def test_string_component_transform_factory_with_LOCALE_and_DUMB_returns_fast_in assert _string_component_transform_factory(ns._DUMB | ns.LOCALE)(x) == fast_int(x, key=lambda x: get_strxfrm()(_groupletters(x))) -@given(text()) +@given(text().filter(bool).filter(no_null)) def test_string_component_transform_factory_with_LOCALE_and_DUMB_returns_fast_int_and_groupletters_and_locale_convert(x): - assume(x) - assume('\0' not in x) try: assert _string_component_transform_factory(ns._DUMB | ns.LOCALE)(x) == fast_int(x, key=lambda x: get_strxfrm()(_groupletters(x))) except ValueError as e: # handle broken locale lib on BSD. diff --git a/test_natsort/test_utils.py b/test_natsort/test_utils.py index f1cffa2..8ae8686 100644 --- a/test_natsort/test_utils.py +++ b/test_natsort/test_utils.py @@ -31,7 +31,6 @@ from slow_splitters import ( ) from compat.locale import low from hypothesis import ( - assume, given, ) from hypothesis.strategies import ( @@ -180,9 +179,8 @@ def test_groupletters_returns_letters_with_lowercase_transform_of_letter_example assert _groupletters('hello') == 'hheelllloo' -@given(text()) +@given(text().filter(bool)) def test_groupeletters_returns_letters_with_lowercase_transform_of_letter(x): - assume(bool(x)) assert _groupletters(x) == ''.join(chain.from_iterable([low(y), y] for y in x)) @@ -200,9 +198,8 @@ def test_sep_inserter_inserts_separator_string_between_two_numbers_example(): assert list(_sep_inserter(iter([5, 9]), null_string)) == [null_string, 5, null_string, 9] -@given(lists(elements=text() | integers())) +@given(lists(elements=text().filter(bool) | integers())) def test_sep_inserter_inserts_separator_between_two_numbers(x): - assume(bool(x)) assert list(_sep_inserter(iter(x), '')) == list(add_leading_space_if_first_is_num(sep_inserter(x, ''), '')) @@ -213,9 +210,8 @@ def test_path_splitter_splits_path_string_by_separator_example(): assert tuple(_path_splitter(z)) == tuple(pathlib.Path(z).parts) -@given(lists(sampled_from(string.ascii_letters), min_size=2)) +@given(lists(sampled_from(string.ascii_letters), min_size=2).filter(all)) def test_path_splitter_splits_path_string_by_separator(x): - assume(all(x)) z = py23_str(pathlib.Path(*x)) assert tuple(_path_splitter(z)) == tuple(pathlib.Path(z).parts) @@ -226,9 +222,8 @@ def test_path_splitter_splits_path_string_by_separator_and_removes_extension_exa assert tuple(_path_splitter(z)) == y[:-1] + (pathlib.Path(z).stem, pathlib.Path(z).suffix) -@given(lists(sampled_from(string.ascii_letters), min_size=3)) +@given(lists(sampled_from(string.ascii_letters), min_size=3).filter(all)) def test_path_splitter_splits_path_string_by_separator_and_removes_extension(x): - assume(all(x)) z = py23_str(pathlib.Path(*x[:-2])) + '.' + x[-1] y = tuple(pathlib.Path(z).parts) assert tuple(_path_splitter(z)) == y[:-1] + (pathlib.Path(z).stem, pathlib.Path(z).suffix) |