def test_resolve_and_run_dependencies_lambda(): text = """ import deal CONST = 34 @deal.post(lambda a: a == CONST) def f(a): return a * 2 """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) tree = astroid.parse(text) print(tree.repr_tree()) funcs2 = Func.from_astroid(tree) for funcs in (funcs1, funcs2): assert len(funcs) == 1 func = funcs[0] assert len(func.contracts) == 1 c = func.contracts[0] assert c.run(12) is False assert c.run(34) is True
def test_arguments(source: str, deps: set): text = """ import deal @deal.post({source}) def f(): return 2 """ text = text.format(source=source) text = dedent(text).strip() tree = ast.parse(text) print(ast.dump(tree)) funcs1 = Func.from_ast(tree) tree = astroid.parse(text) print(tree.repr_tree()) funcs2 = Func.from_astroid(tree) for funcs in (funcs1, funcs2): assert len(funcs) == 1 func = funcs[0] assert len(func.contracts) == 1 c = func.contracts[0] assert c.arguments == deps
def test_exceptions(): funcs1 = Func.from_ast(ast.parse(TEXT)) assert len(funcs1) == 1 funcs2 = Func.from_astroid(astroid.parse(TEXT)) assert len(funcs2) == 1 for func in (funcs1[0], funcs2[0]): assert len(func.contracts) == 1 contract = func.contracts[0] assert contract.exceptions == [ValueError, 'UnknownError']
def test_skip_asserts_in_tests(): checker = CheckAsserts() text = """ def test_example(a): assert False, "oh no!" """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = list(checker(func)) assert actual == []
def test_check_asserts(): checker = CheckAsserts() text = """ def example(a): assert False, "oh no!" """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(2, 11, 'DEAL031 assert error (False)')] assert actual == expected
def test_check_returns_ok_unresolved(): checker = CheckReturns() text = """ @deal.post(unknown) def test(a): return 1 """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = tuple(checker(func)) assert not actual
def test_check_raises_unknown(): checker = CheckRaises() text = """ @deal.raises() def test(a): raise UnknownError """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(3, 10, 'DEAL021 raises contract error (UnknownError)')] assert actual == expected
def test_check_prints(): checker = CheckPrints() text = """ @deal.silent def test(a): print(1) """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(3, 4, 'DEAL022 silent contract error (print)')] assert actual == expected
def test_check_pure(): checker = CheckPure() text = """ @deal.pure def test(a): global b return b """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(3, 4, 'DEAL023 pure contract error (global)')] assert actual == expected
def test_check_prints(): checker = CheckMarkers() text = """ @deal.pure def test(a): print(1) return 1 """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(3, 4, 'DEAL046 missed marker (stdout)')] assert actual == expected
def test_check_pure_no_returns(): checker = CheckMarkers() text = """ @deal.pure def test(a): a + 3 """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] assert len(actual) == 1 expected = 'DEAL043 missed marker (io)' assert actual[0][2] == expected
def test_check_raises_inherited(): checker = CheckRaises() text = """ @deal.raises(LookupError) def test(a): raise KeyError raise ValueError """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(4, 10, 'DEAL021 raises contract error (ValueError)')] assert actual == expected
def test_check_has_no_has(): checker = CheckMarkers() text = """ @deal.pre(lambda a: len(a) > 2) @deal.post(lambda result: result is not None) @deal.raises(ValueError) def test(a): import sys sys.stdout.write(a) """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] assert actual == []
def test_check_pure(): checker = CheckMarkers() text = """ @deal.pure @deal.post(lambda x: x) # skip other contracts def test(a): global b return b """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(4, 4, 'DEAL041 missed marker (global)')] assert actual == expected
def test_check_returns_with_message(): checker = CheckReturns() text = """ @deal.post(lambda x: x > 0 or 'oh no!') def test(a): if a: return 1 else: return -1 """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] expected = [(6, 15, 'DEAL012 oh no! (-1)')] assert actual == expected
def test_simplified_signature(): text = """ import deal @deal.post(lambda _: _.a > _.b) def f(a, b): return a + b """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) assert len(funcs1) == 1 funcs2 = Func.from_astroid(astroid.parse(text)) assert len(funcs2) == 1 for func in (funcs1[0], funcs2[0]): assert len(func.contracts) == 1 c = func.contracts[0] assert c.run(3, 2) is True assert c.run(2, 3) is False
def test_check_has_io(): checker = CheckMarkers() text = """ @deal.pre(lambda a: len(a) > 2) @deal.has('io') @deal.post(lambda result: result is not None) def test(a): import sys sys.stdout.write(a) """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) funcs2 = Func.from_astroid(astroid.parse(text)) for func in (funcs1[0], funcs2[0]): actual = [tuple(err) for err in checker(func)] assert len(actual) == 1 expected = 'DEAL042 missed marker (import)' assert actual[0][2] == expected
def test_return_message(): text = """ import deal @deal.post(lambda x: x > 0 or 'oh no!') def f(x): return x """ text = dedent(text).strip() funcs1 = Func.from_ast(ast.parse(text)) assert len(funcs1) == 1 funcs2 = Func.from_astroid(astroid.parse(text)) assert len(funcs2) == 1 for func in (funcs1[0], funcs2[0]): assert len(func.contracts) == 1 c = func.contracts[0] assert c.run(1) is True assert c.run(-1) == 'oh no!'
def test_unresolvable(): text = """ import deal @deal.post(lambda a: re.compile(unknown)) def f(a): return a * 2 """ text = dedent(text).strip() funcs = Func.from_ast(ast.parse(text)) assert len(funcs) == 1 func = funcs[0] assert len(func.contracts) == 1 c = func.contracts[0] with pytest.raises(NameError): c.run('bcd')
def test_lazy_import_stdlib(): text = """ import deal @deal.post(lambda a: re.compile('^abc$').match(a)) def f(a): return a * 2 """ text = dedent(text).strip() funcs = Func.from_ast(ast.parse(text)) assert len(funcs) == 1 func = funcs[0] assert len(func.contracts) == 1 c = func.contracts[0] assert c.run('bcd') is False assert c.run('abc') is True
def test_resolve_lambda(): text = """ import deal contract = lambda x: x > 0 @deal.post(contract) def f(x): ... """ text = dedent(text).strip() funcs = Func.from_astroid(astroid.parse(text)) assert len(funcs) == 1 func = funcs[0] assert len(func.contracts) == 1 c = func.contracts[0] assert c.run(1) is True assert c.run(-1) is False
def test_resolve_func(): text = """ import deal def contract(x): return x > 0 @deal.post(contract) def f(x): ... """ text = dedent(text).strip() funcs = Func.from_astroid(astroid.parse(text)) assert len(funcs) == 2 func = funcs[-1] assert len(func.contracts) == 1 c = func.contracts[0] assert c.run(1) is True assert c.run(-1) is False
def test_check_has_custom_markers(): checker = CheckMarkers() text = """ import deal @deal.has('database') def inner(): return 1 @deal.has() def outer(): return inner() """ text = dedent(text).strip() funcs = Func.from_astroid(astroid.parse(text)) func = funcs[-1] actual = [tuple(err) for err in checker(func)] assert len(actual) == 1 expected = 'DEAL040 missed marker (database)' assert actual[0][2] == expected
def test_check_pre(): checker = CheckPre() text = """ @deal.pre(lambda x: x > 0) def example(x): return -x @deal.raises() def caller(): return example(-3) # ignore funcs without contracts def caller(): return example(-3) """ text = dedent(text).strip() funcs = Func.from_astroid(astroid.parse(text)) assert len(funcs) == 3 actual = [] for func in funcs: actual.extend(tuple(err) for err in checker(func)) expected = [(7, 11, 'DEAL011 pre contract error (-3)')] assert actual == expected
def test_resolve_and_run_dependencies_func_astroid(): text = """ import deal CONST = 34 def contract(a): return a == CONST @deal.post(contract) def f(a): return a * 2 """ text = dedent(text).strip() tree = astroid.parse(text) print(tree.repr_tree()) funcs = Func.from_astroid(tree) assert len(funcs) == 2 func = funcs[-1] assert len(func.contracts) == 1 c = func.contracts[0] assert c.run(12) is False assert c.run(34) is True
def test_repr(): funcs1 = Func.from_ast(ast.parse(TEXT)) funcs2 = Func.from_astroid(astroid.parse(TEXT)) for func in (funcs1[0], funcs2[0]): assert repr(func) == 'Func(post, raises)'
def test_from_astroid(): funcs = Func.from_astroid(astroid.parse(TEXT)) assert len(funcs) == 3 assert len(funcs[0].contracts) == 2
def test_has_pure_contract(source: str, has: bool) -> None: funcs = Func.from_text(source) assert len(funcs) == 1 assert has_pure_contract(funcs[0]) is has
def test_from_text(): funcs = Func.from_text(TEXT) assert len(funcs) == 3 assert len(funcs[0].contracts) == 2