-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
480 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import deal | ||
import pytest | ||
from typing import NoReturn | ||
|
||
|
||
@deal.raises(ZeroDivisionError) | ||
@deal.pre(lambda a, b: a > 0 and b > 0) | ||
def div(a: int, b: int) -> float: | ||
assert isinstance(a, int) | ||
assert isinstance(b, int) | ||
assert a > 0 | ||
assert b > 0 | ||
return a / b | ||
|
||
func = div | ||
|
||
|
||
def test_count(): | ||
for count in (1, 10, 20, 50): | ||
cases = deal.cases(func, count=count) | ||
assert len(list(cases)) == count | ||
|
||
|
||
def test_params_detected(): | ||
for case in deal.cases(func, count=10): | ||
assert set(case.kwargs) == {'a', 'b'} | ||
|
||
|
||
def test_params_type(): | ||
for case in deal.cases(func, count=10): | ||
assert type(case.kwargs['a']) is int | ||
assert type(case.kwargs['b']) is int | ||
|
||
|
||
def test_params_ok_with_excs(): | ||
results = [] | ||
for case in deal.cases(func, count=20): | ||
result = case() | ||
results.append(result) | ||
assert any(r is not NoReturn for r in results), 'exception occured on every run' | ||
assert any(r is NoReturn for r in results), 'no exception occured' | ||
|
||
|
||
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_explicit_kwargs(): | ||
def div(a: int, b: int): | ||
assert b == 4 | ||
|
||
for case in deal.cases(div, kwargs=dict(b=4), count=20): | ||
case() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import deal | ||
import pytest | ||
import urllib3 | ||
|
||
|
||
def test_chained_contract_decorator(): | ||
|
||
@deal.chain(deal.silent, deal.offline) | ||
def func(msg, do): | ||
if msg: | ||
print(msg) | ||
if do: | ||
http = urllib3.PoolManager() | ||
http.request('GET', 'http://httpbin.org/robots.txt') | ||
|
||
func(False, False) | ||
with pytest.raises(deal.SilentContractError): | ||
func(True, False) | ||
with pytest.raises(deal.OfflineContractError): | ||
func(False, True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import deal | ||
import pytest | ||
|
||
|
||
def test_parameters_and_result_fulfill_constact(): | ||
@deal.ensure(lambda a, b, result: a > 0 and b > 0 and result != 'same number') | ||
def func(a, b): | ||
if a == b: | ||
return 'same number' | ||
else: | ||
return 'different numbers' | ||
|
||
assert func(1, 2) == 'different numbers' | ||
with pytest.raises(deal.PostContractError): | ||
func(0, 1) | ||
with pytest.raises(deal.PostContractError): | ||
func(1, 0) | ||
with pytest.raises(deal.PostContractError): | ||
func(1, 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import deal | ||
import pytest | ||
|
||
|
||
def test_setting_object_attribute_fulfills_contract(): | ||
@deal.inv(lambda obj: obj.x > 0) | ||
class A: | ||
x = 2 | ||
|
||
a = A() | ||
a.x = 4 | ||
with pytest.raises(deal.InvContractError): | ||
a.x = -2 | ||
|
||
|
||
def test_setting_wrong_args_by_method_raises_error(): | ||
@deal.inv(lambda obj: obj.x > 0) | ||
class A: | ||
x = 2 | ||
|
||
def f(self, x): | ||
self.x = x | ||
|
||
a = A() | ||
|
||
a.f(4) | ||
with pytest.raises(deal.InvContractError): | ||
a.f(-2) | ||
|
||
|
||
def test_chain_contracts_both_fulfill(): | ||
@deal.inv(lambda obj: obj.x > 0) | ||
@deal.inv(lambda obj: obj.x < 10) | ||
class A: | ||
x = 2 | ||
|
||
a = A() | ||
a.x = 4 | ||
with pytest.raises(deal.InvContractError): | ||
a.x = -2 | ||
with pytest.raises(deal.InvContractError): | ||
a.x = 20 | ||
|
||
|
||
def test_patched_invariants_instance(): | ||
class A: | ||
x = 2 | ||
|
||
PatchedA = deal.inv(lambda obj: obj.x > 0)(A) # noQA | ||
a = PatchedA() | ||
assert isinstance(a, PatchedA) | ||
assert isinstance(a, A) | ||
|
||
PatchedA2 = deal.inv(lambda obj: obj.x > 0)(PatchedA) # noQA | ||
a = PatchedA2() | ||
assert isinstance(a, PatchedA) | ||
assert isinstance(a, PatchedA2) | ||
assert isinstance(a, A) | ||
|
||
assert a.__class__.__name__.count('Invarianted') == 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import marshmallow | ||
import vaa | ||
|
||
import deal | ||
import pytest | ||
|
||
|
||
@pytest.fixture() | ||
def scheme(): | ||
class _Scheme(marshmallow.Schema): | ||
name = marshmallow.fields.Str() | ||
yield vaa.marshmallow(_Scheme) | ||
|
||
|
||
def test_scheme_string_validation_args_correct(scheme): | ||
@deal.pre(scheme) | ||
def func(name): | ||
return name * 2 | ||
|
||
assert func('Chris') == 'ChrisChris' | ||
|
||
with pytest.raises(deal.PreContractError): | ||
func(123) | ||
|
||
try: | ||
func(123) | ||
except deal.PreContractError as e: | ||
assert e.args[0] == {'name': ['Not a valid string.']} | ||
|
||
|
||
def test_method_chain_decorator_with_scheme_is_fulfilled(scheme): | ||
@deal.pre(scheme) | ||
@deal.pre(lambda name: name != 'Oleg') | ||
def func(name): | ||
return name * 2 | ||
|
||
assert func('Chris') == 'ChrisChris' | ||
|
||
with pytest.raises(deal.PreContractError): | ||
func(123) | ||
|
||
with pytest.raises(deal.PreContractError): | ||
func('Oleg') | ||
|
||
|
||
def test_scheme_contract_is_satisfied_when_setting_arg(scheme): | ||
@deal.inv(scheme) | ||
class User: | ||
name = '' | ||
|
||
user = User() | ||
|
||
user.name = 'Chris' | ||
|
||
with pytest.raises(deal.InvContractError): | ||
user.name = 123 | ||
|
||
try: | ||
user.name = 123 | ||
except deal.InvContractError as e: | ||
assert e.args[0] == {'name': ['Not a valid string.']} | ||
|
||
|
||
def test_scheme_contract_is_satisfied_within_chain(scheme): | ||
@deal.inv(lambda user: user.name != 'Oleg') | ||
@deal.inv(scheme) | ||
@deal.inv(lambda user: user.name != 'Chris') | ||
class User: | ||
name = '' | ||
|
||
user = User() | ||
user.name = 'Gram' | ||
|
||
user = User() | ||
with pytest.raises(deal.InvContractError): | ||
user.name = 'Oleg' | ||
|
||
user = User() | ||
with pytest.raises(deal.InvContractError): | ||
user.name = 123 | ||
|
||
user = User() | ||
with pytest.raises(deal.InvContractError): | ||
user.name = 'Chris' | ||
|
||
|
||
def test_scheme_contract_is_satisfied_when_passing_args(scheme): | ||
@deal.pre(scheme) | ||
def func(name): | ||
return name * 2 | ||
|
||
assert func('Chris') == 'ChrisChris' | ||
|
||
assert func(name='Chris') == 'ChrisChris' | ||
|
||
@deal.pre(scheme) | ||
def func(**kwargs): | ||
return kwargs['name'] * 3 | ||
|
||
assert func(name='Chris') == 'ChrisChrisChris' | ||
|
||
@deal.pre(scheme) | ||
def func(name='Max'): | ||
return name * 2 | ||
|
||
assert func() == 'MaxMax' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import deal | ||
import pytest | ||
import urllib3 | ||
|
||
|
||
def test_network_request_in_offline_raises_exception(): | ||
|
||
@deal.offline | ||
def func(do): | ||
if do: | ||
http = urllib3.PoolManager() | ||
http.request('GET', 'http://httpbin.org/robots.txt') | ||
|
||
func(False) | ||
with pytest.raises(deal.OfflineContractError): | ||
func(True) | ||
|
||
|
||
def test_network_request_in_offline_and_raises_specified_exception(): | ||
|
||
@deal.offline(exception=KeyError) | ||
def func(do): | ||
if do: | ||
http = urllib3.PoolManager() | ||
http.request('GET', 'http://httpbin.org/robots.txt') | ||
|
||
func(False) | ||
with pytest.raises(KeyError): | ||
func(True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import deal | ||
import pytest | ||
|
||
|
||
def test_return_value_fulfils_contract(): | ||
func = deal.post(lambda x: x > 0)(lambda x: -x) | ||
assert func(-4) == 4 | ||
|
||
with pytest.raises(deal.PostContractError): | ||
func(4) |
Oops, something went wrong.