Skip to content

Commit

Permalink
Merge f6c4b14 into 3005f95
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalsodani committed Oct 7, 2019
2 parents 3005f95 + f6c4b14 commit 7ba87c4
Show file tree
Hide file tree
Showing 12 changed files with 475 additions and 0 deletions.
Empty file added tests/__init__.py
Empty file.
64 changes: 64 additions & 0 deletions tests/test_case.py
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()
20 changes: 20 additions & 0 deletions tests/test_chain.py
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)
19 changes: 19 additions & 0 deletions tests/test_ensure.py
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)
60 changes: 60 additions & 0 deletions tests/test_inv.py
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
106 changes: 106 additions & 0 deletions tests/test_marshmallow.py
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'
29 changes: 29 additions & 0 deletions tests/test_offline.py
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)
10 changes: 10 additions & 0 deletions tests/test_post.py
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)
Loading

0 comments on commit 7ba87c4

Please sign in to comment.