Last active
October 12, 2017 18:13
-
-
Save rvprasad/208105655e1d3f401165306963dea1dd to your computer and use it in GitHub Desktop.
A script to demonstrate how to use property-based testing to test str_to_int function. Not all tests are required.
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
# Python -- v3.6 | |
# https://docs.pytest.org/en/latest/ -- v3.2.1 | |
# http://hypothesis.readthedocs.io/en/latest/ -- v3.7 | |
from hypothesis import assume, given | |
from hypothesis.strategies import text | |
import pytest | |
rep2int = { | |
'1':1, | |
'2':2, | |
'3':3, | |
'4':4, | |
'5':5, | |
'6':6, | |
'7':7, | |
'8':8, | |
'9':9, | |
'0':0 | |
} | |
def str_to_int(s): | |
''' | |
Return X if s represents a valid integer X | |
Raise ValueError if s does not represent a valid integer | |
''' | |
tmp1 = list(s) | |
tmp1.reverse() | |
val = 0 | |
pos = 0 | |
signSeen = False | |
numSeen = False | |
for i in tmp1: | |
if i in rep2int: | |
val += rep2int[i] * (10 ** pos) | |
numSeen = True | |
elif i == '-' or i == '+': | |
if signSeen: | |
raise ValueError("Invalid repr") | |
val *= -1 if i == '-' else 1 | |
signSeen = True | |
else: | |
raise ValueError("Invalid repr") | |
pos += 1 | |
if not numSeen: | |
raise ValueError("Invalid repr") | |
return val | |
@given(text(min_size=1, max_size=15)) | |
def test_invalid_repr(s): | |
# assume clause can be simplified by using regex | |
assume( | |
not( | |
all(i in list('1234567890-+') for i in s) and | |
s.count('-') + s.count('+') < 2 and | |
(s.count('-') == 0 or s.index('-') == 0 and len(s) > 1) and | |
(s.count('+') == 0 or s.index('+') == 0 and len(s) > 1) | |
) | |
) | |
with pytest.raises(ValueError): | |
str_to_int(s) | |
@given(text(alphabet='+1234567890', min_size=1, max_size=15)) | |
def test_positive_int_repr(s): | |
assume( | |
s.count('+') < 2 and | |
(s.count('+') == 0 or s.index('+') == 0 and len(s) > 1) | |
) | |
if all(i in ['0', '+'] for i in s): | |
assert str_to_int(s) == 0 | |
else: | |
assert str_to_int(s) > 0 | |
@given(text(alphabet='-1234567890', min_size=1, max_size=15)) | |
def test_negative_int_repr(s): | |
assume(s.count('-') == 1 and s.index('-') == 0 and len(s) > 1) | |
# assuming we deem -0 as valid repr | |
if all(i in ['0', '-'] for i in s): | |
assert str_to_int(s) == 0 | |
else: | |
assert str_to_int(s) < 0 | |
@given(text(alphabet='1234567890', min_size=1, max_size=1)) | |
def test_single_digit_int_repr(s): | |
assert str_to_int(s) == rep2int[s] | |
@given(text(alphabet='-+1234567890', min_size=1, max_size=15)) | |
def test_multi_digit_int_repr(s): | |
assume( | |
s.count('-') + s.count('+') < 2 and | |
(s.count('-') == 0 or s.index('-') == 0 and len(s) > 1) and | |
(s.count('+') == 0 or s.index('+') == 0 and len(s) > 1) | |
) | |
val = str_to_int(s) | |
revS = list(s) | |
sgn = 1 | |
if revS[0] == '+': | |
del revS[0] | |
if revS[0] == '-': | |
del revS[0] | |
sgn = -1 | |
revS.reverse() | |
for i in range(0, len(revS)): | |
tmp1 = str_to_int(revS[i]) | |
tmp2 = val * sgn // (10 ** i) | |
tmp3 = tmp2 - (tmp2 // 10) * 10 | |
assert tmp1 == tmp3 | |
@given(text(alphabet='+-1234567890', min_size=1, max_size=15)) | |
def test_convert_back(s): | |
assume( | |
s.count('-') + s.count('+') < 2 and | |
(s.count('-') == 0 or s.index('-') == 0 and len(s) > 1) and | |
(s.count('+') == 0 or s.index('+') == 0 and len(s) > 1) | |
) | |
# this would be the simplest test for all valid repr | |
tmp1 = "" | |
sgn = '' | |
nonZeroSeen = False | |
for i in s: | |
if i == '-': | |
sgn = '-' | |
elif i == '+': | |
pass | |
elif i != '0': | |
nonZeroSeen = True | |
if nonZeroSeen: | |
tmp1 += i | |
tmp1 = sgn + tmp1 if tmp1 else '0' | |
assert str(str_to_int(s)) == tmp1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment