def test_count(): for count in (1, 10, 20, 50): cases = deal.cases(div1, count=count) assert len(list(cases)) == count cases = deal.cases(div2, count=count) assert len(list(cases)) == count
def test_params_type(): for case in deal.cases(div1, count=10): assert type(case.kwargs['a']) is int assert type(case.kwargs['b']) is int for case in deal.cases(div2, count=10): assert type(case.kwargs['a']) is int assert type(case.kwargs['b']) is int
def test_return_type_checks(): def div(a: int, b: int): return 1 for case in deal.cases(div, count=20): case() def div(a: int, b: int) -> str: return 1 with pytest.raises(TypeError): case = next(iter(deal.cases(div, count=20))) case()
def test_params_ok_with_excs(): results = [] for case in deal.cases(div1, count=20): result = case() results.append(result) assert len(results) == 20 assert any(r is NoReturn for r in results), 'no exception occured'
def benchmark_deal(arg_count: int = 1) -> None: """Benchmark the Hypothesis testing with deal.""" count = 0 if arg_count == 1: @deal.pre(lambda _: _.a > 0) def some_func(a: int) -> None: nonlocal count count += 1 pass for case in deal.cases(some_func, count=100): case() elif arg_count == 2: @deal.pre(lambda _: _.a > 0) @deal.pre(lambda _: _.b > 0) def some_func(a: int, b: int) -> None: nonlocal count count += 1 pass for case in deal.cases(some_func, count=100): case() elif arg_count == 3: @deal.pre(lambda _: _.a > 0) @deal.pre(lambda _: _.b > 0) @deal.pre(lambda _: _.c > 0) def some_func(a: int, b: int, c: int) -> None: nonlocal count count += 1 pass for case in deal.cases(some_func, count=100): case() else: raise NotImplementedError("arg_count {}".format(arg_count)) assert count == 100
def test_explicit_strategy(): def div(a: int, b: int): assert 0 <= b <= 4 cases = deal.cases( div, kwargs=dict(b=hypothesis.strategies.integers(min_value=0, max_value=4)), count=20, ) for case in cases: case()
def test_disable_type_checks(): def bad(a: int) -> str: return a # type is wrong and checked cases = deal.cases(bad, count=1) case = next(cases) msg = 'type of the return value must be str; got int instead' with pytest.raises(TypeError, match=msg): case() # type is wrong and ignored cases = deal.cases(bad, count=1, check_types=False) case = next(cases) case() def good(a: int) -> int: return a # type is good cases = deal.cases(good, count=1) case = next(cases) case()
# built-in import random from typing import List # external import pytest # project import deal # the list cannot be empty @deal.pre(lambda items: bool(items)) # result is an element withit the given list @deal.ensure(lambda items, result: result in items) @deal.has() def choice(items: List[str]) -> str: """Get a random element from the given list. """ return random.choice(items) @pytest.mark.parametrize('case', deal.cases(choice)) def test_choice(case): case()
# element at this position matches item deal.ensure( lambda items, item, result: items[result] == item, message='invalid match', ), # element at this position is the first match deal.ensure( lambda items, item, result: not any(el == item for el in items[:result]), message='not the first match', ), # LookupError will be raised if no elements found deal.raises(LookupError), deal.reason(LookupError, lambda items, item: item not in items), # no side-effects deal.has(), ) @contract_for_index_of def index_of(items: List[int], item: int) -> int: for index, el in enumerate(items): if el == item: return index raise LookupError @pytest.mark.parametrize('case', deal.cases(index_of)) def test_index_of(case): case()
from typing import List, TypeVar import deal import pytest T = TypeVar('T') @deal.pre(lambda items: len(items) > 0) @deal.has() def my_min(items: List[T]) -> T: return min(items) @deal.has('stdout') def example(): # good print(my_min([3, 1, 4])) # bad print(my_min([])) @pytest.mark.parametrize('case', deal.cases(my_min)) def test_min(case): case()
deal.post(lambda result: result >= 0), deal.ensure(lambda items, item, result: result < len(items)), # element at this position matches item deal.ensure( lambda items, item, result: items[result] == item, message='invalid match', ), # element at this position is the first match deal.ensure( lambda items, item, result: not any(el == item for el in items[:result]), message='not the first match', ), # LookupError will be raised if no elements found deal.raises(LookupError), deal.reason(LookupError, lambda items, item: item not in items), # no side-effects deal.has(), ) @contract_for_index_of def index_of(items: List[int], item: int) -> int: for index, el in enumerate(items): if el == item: return index raise LookupError test_index_of = deal.cases(index_of)
def fuzz(): test = deal.cases(decode) PythonFuzz(test)()
# built-in from typing import List # project import deal @deal.pre(lambda items: len(items) > 0) @deal.has() def my_min(items: List[int]) -> int: return min(items) @deal.has('stdout') def example(): # good print(my_min([3, 1, 4])) # bad print(my_min([])) test_min = deal.cases(my_min)
import deal from hypothesis.strategies import lists, one_of from flake_master.utils.requirements import merge_requirements_data from flake_master.utils.testing_strategies import requirement test_merge_requirements_data = deal.cases( merge_requirements_data, kwargs={ 'raw_old_requirements': lists( one_of( requirement(with_version=True, with_comment=True), requirement(with_version=True, with_comment=False), requirement(with_version=False, with_comment=True), requirement(with_version=False, with_comment=False), requirement(only_comment=True), ), ), }) def test_merge_requirements_data_succes_case(): actual_result = merge_requirements_data( raw_old_requirements=['foo', 'bar==1.2', 'baz>=2.0'], flake8_plugins=[('bar', '2.1'), ('bax', '5')], ) assert actual_result == '''foo bar==2.1 baz>=2.0 bax==5 '''
# built-in import random from typing import List # project import deal # the list cannot be empty @deal.pre(lambda items: bool(items)) # result is an element withit the given list @deal.ensure(lambda items, result: result in items) @deal.has() def choice(items: List[str]) -> str: """Get a random element from the given list. """ return random.choice(items) test_choice = deal.cases(choice)
import deal from flake_master.utils.presets import ( extract_preset_file_path, extract_preset_url, extract_preset_credentials, ) test_extract_preset_file_path = deal.cases(extract_preset_file_path) test_extract_preset_url = deal.cases(extract_preset_url) test_extract_preset_credentials = deal.cases(extract_preset_credentials)
# project import deal @deal.raises(ZeroDivisionError) @deal.reason(ZeroDivisionError, lambda _: _.right == 0) @deal.has() def div1(left: float, right: float) -> float: """ This implementation allows zero to be passed but raises ZeroDivisionError in that case. """ return left / right @deal.pre(lambda _: _.right != 0) @deal.has() def div2(left: float, right: float) -> float: """ This implementation doesn't allow zero to be passed in a function. If it is accidentally passed, PreConditionError will be raised and the funcrion won't be executed. """ return left / right test_div1 = deal.cases(div1) test_div2 = deal.cases(div2)
def test_params_detected(): for case in deal.cases(func, count=10): assert set(case.kwargs) == {'a', 'b'}
# built-in from typing import List # project import deal # In short signature, `_` is a `dict` with access by attributes. # Hence it has all dict attributes. So, if argument we need conflicts # with a dict attribute, use getitem instead of getattr. # In the example below, we use `_['items']` instead of `_.items`. @deal.post(lambda result: result >= 0) # if count is not zero, `item` appears in `items` at least once. @deal.ensure(lambda _: _.result == 0 or _['item'] in _['items']) # if count is zero, `item` is not in `items` @deal.ensure(lambda _: _.result != 0 or _['item'] not in _['items']) @deal.has() def count(items: List[str], item: str) -> int: """How many times `item` appears in `items` """ return items.count(item) test_count = deal.cases(count)
def test_no_bad_examples(): for case in deal.cases(div2, count=20): assert case.kwargs['a'] > 0 assert case.kwargs['b'] > 0
# built-in from typing import List # external import pytest # project import deal # In short signature, `_` is a `dict` with access by attributes. # Hence it has all dict attributes. So, if argument we need conflicts # with a dict attribute, use getitem instead of getattr. # In the example below, we use `_['items']` instead of `_.items`. @deal.post(lambda result: result >= 0) # if count is not zero, `item` appears in `items` at least once. @deal.ensure(lambda _: _.result == 0 or _['item'] in _['items']) # if count is zero, `item` is not in `items` @deal.ensure(lambda _: _.result != 0 or _['item'] not in _['items']) @deal.has() def count(items: List[str], item: str) -> int: """How many times `item` appears in `items` """ return items.count(item) @pytest.mark.parametrize('case', deal.cases(count)) def test_count(case: deal.TestCase): case()
def test_explicit_kwargs(): def div(a: int, b: int): assert b == 4 for case in deal.cases(div, kwargs=dict(b=4), count=20): case()
def fuzz(): test = deal.cases(decode) atheris.Setup(sys.argv, test) atheris.Fuzz()
# project import deal @deal.ensure(lambda _: _.result.startswith(_.left)) @deal.ensure(lambda _: _.result.endswith(_.right)) @deal.ensure(lambda _: len(_.result) == len(_.left) + len(_.right)) @deal.has() def concat(left: str, right: str) -> str: """Concatenate 2 given strings. https://deal.readthedocs.io/basic/motivation.html """ return left + right test_concat = deal.cases(concat)