Feature/delete rec additional test data set (#133)
* new: test: additional data test set. * new: test: test on non integer. * chg: test: rename function for consistency. * chg: test: change normalize function. * chg: test: change max value for high var * fix: test: use normalized index * fix: test: remove 'max' as valid value * chg: test: use hypothesis to test delete_rec index * new: test: add hypothesis package * chg: test: use hypothesis to test delete_rec index * chg: test: add hypothesis to travis * chg: test: limit integer test. * chg: dev: remove unused test * fix: test: fix test on non integer. * new: test: add big integer test on range in delete_rec method. * fix: test: fix high low diff * fix: test: skip only for python<3.5 * chg: test: change test_delete_rec_range_and_big_int - remove skip - use constant value instead sys.maxsize - fix assert * chg: test: use setup.py to manage test package instead travis * chg: test: add tests extras on setup.py * chg: test: change install test package. * fix: test: fix whitespace * fix: test: MAX_SQLITE_INT value * chg: test: skip test for python<3.5 * fix: test: fix import * chg: test: skip Impossible test * chg: test: simplify test_delete_rec_on_non_interger
This commit is contained in:
parent
50c6593bb8
commit
0c7d5cfe97
@ -4,7 +4,7 @@ python:
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
before_install:
|
||||
- pip install pytest pytest-cov pytest-catchlog
|
||||
- "pip install -e .[tests]"
|
||||
install: "pip install -r requirements.txt"
|
||||
addons:
|
||||
apt:
|
||||
|
7
setup.py
7
setup.py
@ -15,6 +15,8 @@ with open('buku.py', encoding='utf-8') as f:
|
||||
with open('README.md', encoding='utf-8') as f:
|
||||
long_description = f.read()
|
||||
|
||||
tests_require = ['pytest-cov', 'pytest-catchlog', 'hypothesis==3.7.0'],
|
||||
|
||||
setup(
|
||||
name='buku',
|
||||
version=version,
|
||||
@ -33,10 +35,11 @@ setup(
|
||||
'HTTP': ['urllib3'],
|
||||
'CRYPTO': ['cryptography'],
|
||||
'HTML': ['beautifulsoup4'],
|
||||
'REQUESTS': ['requests']
|
||||
'REQUESTS': ['requests'],
|
||||
'tests': tests_require,
|
||||
},
|
||||
test_suite='tests',
|
||||
tests_require=['pytest-cov', 'pytest-catchlog'],
|
||||
tests_require=tests_require,
|
||||
keywords='cli bookmarks tag utility',
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
|
@ -2,16 +2,20 @@
|
||||
#
|
||||
# Unit test cases for buku
|
||||
#
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import sqlite3
|
||||
import sys
|
||||
from genericpath import exists
|
||||
from itertools import product
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from hypothesis import given, example
|
||||
from hypothesis import strategies as st
|
||||
from unittest import mock as mock
|
||||
import pytest
|
||||
import unittest
|
||||
from unittest import mock as mock
|
||||
|
||||
from buku import BukuDb, parse_tags, prompt
|
||||
|
||||
@ -19,6 +23,7 @@ TEST_TEMP_DIR_OBJ = TemporaryDirectory(prefix='bukutest_')
|
||||
TEST_TEMP_DIR_PATH = TEST_TEMP_DIR_OBJ.name
|
||||
TEST_TEMP_DBDIR_PATH = os.path.join(TEST_TEMP_DIR_PATH, 'buku')
|
||||
TEST_TEMP_DBFILE_PATH = os.path.join(TEST_TEMP_DBDIR_PATH, 'bookmarks.db')
|
||||
MAX_SQLITE_INT = int(math.pow(2, 63) - 1)
|
||||
|
||||
TEST_BOOKMARKS = [
|
||||
['http://slashdot.org',
|
||||
@ -35,6 +40,8 @@ TEST_BOOKMARKS = [
|
||||
"a case for replace_tag test"],
|
||||
]
|
||||
|
||||
only_python_3_5 = pytest.mark.skipif(sys.version_info < (3, 5), reason="requires python3.5")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def setup():
|
||||
@ -490,93 +497,14 @@ def test_compactdb(setup):
|
||||
assert bdb.get_rec_by_id(3) is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'index, low, high, is_range',
|
||||
product(
|
||||
[-1, 0],
|
||||
[-1, 0],
|
||||
[-1, 0],
|
||||
[True, False]
|
||||
)
|
||||
@given(
|
||||
low=st.integers(min_value=-10, max_value=10),
|
||||
high=st.integers(min_value=-10, max_value=10),
|
||||
delay_commit=st.booleans(),
|
||||
input_retval=st.characters()
|
||||
)
|
||||
def test_delete_rec_negative(setup, index, low, high, is_range):
|
||||
"""test when index, low or high is less than 0."""
|
||||
bdb = BukuDb()
|
||||
|
||||
# Fill bookmark
|
||||
for bookmark in TEST_BOOKMARKS:
|
||||
bdb.add_rec(*bookmark)
|
||||
db_len = len(TEST_BOOKMARKS)
|
||||
|
||||
with mock.patch('builtins.input', return_value='y'):
|
||||
res = bdb.delete_rec(index=index, low=low, high=high, is_range=is_range)
|
||||
if is_range and any([low < 0, high < 0]):
|
||||
assert not res
|
||||
assert db_len == len(bdb.get_rec_all())
|
||||
elif not is_range and index < 0:
|
||||
assert not res
|
||||
assert db_len == len(bdb.get_rec_all())
|
||||
else:
|
||||
assert res
|
||||
with pytest.raises(sqlite3.OperationalError):
|
||||
assert len(bdb.get_rec_all()) == 0
|
||||
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'is_range, input_retval, high, low',
|
||||
product(
|
||||
[True, False],
|
||||
['y', 'n'],
|
||||
[0, 1],
|
||||
[0, 1],
|
||||
)
|
||||
)
|
||||
def test_delete_rec_cleardb(setup, is_range, input_retval, high, low):
|
||||
"""test scenario when meet cleardb function."""
|
||||
bdb = BukuDb()
|
||||
index = 0
|
||||
|
||||
# Fill bookmark
|
||||
for bookmark in TEST_BOOKMARKS:
|
||||
bdb.add_rec(*bookmark)
|
||||
db_len = len(TEST_BOOKMARKS)
|
||||
|
||||
with mock.patch('builtins.input', return_value=input_retval):
|
||||
res = bdb.delete_rec(index=index, low=low, high=high, is_range=is_range)
|
||||
if is_range and high == 1 and low == 1:
|
||||
assert res
|
||||
assert len(bdb.get_rec_all()) == db_len - 1
|
||||
elif is_range and input_retval != 'y':
|
||||
assert not res
|
||||
assert len(bdb.get_rec_all()) == db_len
|
||||
elif is_range:
|
||||
assert res
|
||||
with pytest.raises(sqlite3.OperationalError):
|
||||
bdb.get_rec_all()
|
||||
elif input_retval != 'y':
|
||||
assert not res
|
||||
assert len(bdb.get_rec_all()) == db_len
|
||||
else:
|
||||
assert res
|
||||
with pytest.raises(sqlite3.OperationalError):
|
||||
bdb.get_rec_all()
|
||||
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'low, high, delay_commit',
|
||||
product(
|
||||
[1, 1000],
|
||||
[1, 1000],
|
||||
[True, False],
|
||||
)
|
||||
)
|
||||
def test_delete_rec_range_and_delay_commit(setup, low, high, delay_commit):
|
||||
@example(low=0, high=0, delay_commit=False, input_retval='y')
|
||||
def test_delete_rec_range_and_delay_commit(setup, low, high, delay_commit, input_retval):
|
||||
"""test delete rec, range and delay commit."""
|
||||
bdb = BukuDb()
|
||||
bdb_dc = BukuDb() # instance for delay_commit check.
|
||||
@ -589,10 +517,7 @@ def test_delete_rec_range_and_delay_commit(setup, low, high, delay_commit):
|
||||
db_len = len(TEST_BOOKMARKS)
|
||||
|
||||
# use normalized high and low variable
|
||||
if low > high:
|
||||
n_low, n_high = high, low
|
||||
else:
|
||||
n_low, n_high = low, high
|
||||
n_low, n_high = normalize_range(db_len=db_len, low=low, high=high)
|
||||
|
||||
exp_res = True
|
||||
if n_high > db_len and n_low <= db_len:
|
||||
@ -603,10 +528,37 @@ def test_delete_rec_range_and_delay_commit(setup, low, high, delay_commit):
|
||||
elif n_high == n_low and n_low <= db_len:
|
||||
exp_db_len = db_len - 1
|
||||
else:
|
||||
exp_db_len = db_len - (n_high - n_low)
|
||||
exp_db_len = db_len - (n_high + 1 - n_low)
|
||||
|
||||
res = bdb.delete_rec(
|
||||
index=index, low=low, high=high, is_range=is_range, delay_commit=delay_commit)
|
||||
with mock.patch('builtins.input', return_value=input_retval):
|
||||
res = bdb.delete_rec(
|
||||
index=index, low=low, high=high, is_range=is_range, delay_commit=delay_commit)
|
||||
|
||||
if (low == 0 or high == 0) and input_retval != 'y':
|
||||
assert not res
|
||||
assert len(bdb_dc.get_rec_all()) == db_len
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
return
|
||||
elif (low == 0 or high == 0) and input_retval == 'y':
|
||||
assert res == exp_res
|
||||
with pytest.raises(sqlite3.OperationalError):
|
||||
bdb.get_rec_all()
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
return
|
||||
elif n_low > db_len and n_low > 0:
|
||||
assert not res
|
||||
assert len(bdb_dc.get_rec_all()) == db_len
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
return
|
||||
elif n_low < 0:
|
||||
assert not res
|
||||
assert len(bdb_dc.get_rec_all()) == db_len
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
return
|
||||
assert res == exp_res
|
||||
assert len(bdb.get_rec_all()) == exp_db_len
|
||||
if delay_commit:
|
||||
@ -618,14 +570,34 @@ def test_delete_rec_range_and_delay_commit(setup, low, high, delay_commit):
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
|
||||
|
||||
@only_python_3_5
|
||||
@pytest.mark.skip(reason='Impossible case.')
|
||||
@pytest.mark.parametrize(
|
||||
'index, delay_commit',
|
||||
'low, high',
|
||||
product(
|
||||
[1, 1000],
|
||||
[True, False],
|
||||
[1, MAX_SQLITE_INT + 1],
|
||||
[1, MAX_SQLITE_INT + 1],
|
||||
)
|
||||
)
|
||||
def test_delete_rec_index_and_delay_commit(index, delay_commit):
|
||||
def test_delete_rec_range_and_big_int(setup, low, high):
|
||||
"""test delete rec, range and big integer."""
|
||||
bdb = BukuDb()
|
||||
index = 0
|
||||
is_range = True
|
||||
|
||||
# Fill bookmark
|
||||
for bookmark in TEST_BOOKMARKS:
|
||||
bdb.add_rec(*bookmark)
|
||||
db_len = len(TEST_BOOKMARKS)
|
||||
res = bdb.delete_rec(index=index, low=low, high=high, is_range=is_range)
|
||||
if high > db_len and low > db_len:
|
||||
assert not res
|
||||
return
|
||||
assert res
|
||||
|
||||
|
||||
@given(index=st.integers(), delay_commit=st.booleans(), input_retval=st.booleans())
|
||||
def test_delete_rec_index_and_delay_commit(index, delay_commit, input_retval):
|
||||
"""test delete rec, index and delay commit."""
|
||||
bdb = BukuDb()
|
||||
bdb_dc = BukuDb() # instance for delay_commit check.
|
||||
@ -635,9 +607,22 @@ def test_delete_rec_index_and_delay_commit(index, delay_commit):
|
||||
bdb.add_rec(*bookmark)
|
||||
db_len = len(TEST_BOOKMARKS)
|
||||
|
||||
res = bdb.delete_rec(index=index, delay_commit=delay_commit)
|
||||
n_index = index
|
||||
|
||||
if index > db_len:
|
||||
if index.bit_length() > 63:
|
||||
with pytest.raises(OverflowError):
|
||||
bdb.delete_rec(index=index, delay_commit=delay_commit)
|
||||
return
|
||||
|
||||
with mock.patch('builtins.input', return_value=input_retval):
|
||||
res = bdb.delete_rec(index=index, delay_commit=delay_commit)
|
||||
|
||||
if n_index < 0:
|
||||
assert not res
|
||||
elif n_index > db_len:
|
||||
assert not res
|
||||
assert len(bdb.get_rec_all()) == db_len
|
||||
elif index == 0 and input_retval != 'y':
|
||||
assert not res
|
||||
assert len(bdb.get_rec_all()) == db_len
|
||||
else:
|
||||
@ -663,7 +648,7 @@ def test_delete_rec_index_and_delay_commit(index, delay_commit):
|
||||
(0, False, 0, 0),
|
||||
]
|
||||
)
|
||||
def test_get_delete_rec_on_empty_database(setup, index, is_range, low, high):
|
||||
def test_delete_rec_on_empty_database(setup, index, is_range, low, high):
|
||||
"""test delete rec, on empty database."""
|
||||
bdb = BukuDb()
|
||||
with mock.patch('builtins.input', return_value='y'):
|
||||
@ -681,6 +666,35 @@ def test_get_delete_rec_on_empty_database(setup, index, is_range, low, high):
|
||||
# teardown
|
||||
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'index, low, high, is_range',
|
||||
[
|
||||
['a', 'a', 1, True],
|
||||
['a', 'a', 1, False],
|
||||
['a', 1, 'a', True],
|
||||
]
|
||||
)
|
||||
def test_delete_rec_on_non_interger(index, low, high, is_range):
|
||||
"""test delete rec on non integer arg."""
|
||||
bdb = BukuDb()
|
||||
|
||||
for bookmark in TEST_BOOKMARKS:
|
||||
bdb.add_rec(*bookmark)
|
||||
db_len = len(TEST_BOOKMARKS)
|
||||
|
||||
if is_range and not (isinstance(low, int) and isinstance(high, int)):
|
||||
with pytest.raises(TypeError):
|
||||
bdb.delete_rec(index=index, low=low, high=high, is_range=is_range)
|
||||
return
|
||||
elif not is_range and not isinstance(index, int):
|
||||
res = bdb.delete_rec(index=index, low=low, high=high, is_range=is_range)
|
||||
assert not res
|
||||
assert len(bdb.get_rec_all()) == db_len
|
||||
else:
|
||||
assert bdb.delete_rec(index=index, low=low, high=high, is_range=is_range)
|
||||
|
||||
|
||||
# Helper functions for testcases
|
||||
|
||||
|
||||
@ -693,5 +707,47 @@ def split_and_test_membership(a, b):
|
||||
def inclusive_range(start, end):
|
||||
return range(start, end + 1)
|
||||
|
||||
|
||||
def normalize_range(db_len, low, high):
|
||||
"""normalize index and range.
|
||||
|
||||
Args:
|
||||
db_len (int): database length.
|
||||
low (int): low limit.
|
||||
high (int): high limit.
|
||||
|
||||
Returns:
|
||||
Tuple contain following normalized variables (low, high)
|
||||
"""
|
||||
require_comparison = True
|
||||
# don't deal with non instance of the variable.
|
||||
if not isinstance(low, int):
|
||||
n_low = low
|
||||
require_comparison = False
|
||||
if not isinstance(high, int):
|
||||
n_high = high
|
||||
require_comparison = False
|
||||
|
||||
max_value = db_len
|
||||
if low == 'max' and high == 'max':
|
||||
n_low = db_len
|
||||
n_high = max_value
|
||||
elif low == 'max' and high != 'max':
|
||||
n_low = high
|
||||
n_high = max_value
|
||||
elif low != 'max' and high == 'max':
|
||||
n_low = low
|
||||
n_high = max_value
|
||||
else:
|
||||
n_low = low
|
||||
n_high = high
|
||||
|
||||
if require_comparison:
|
||||
if n_high < n_low:
|
||||
n_high, n_low = n_low, n_high
|
||||
|
||||
return (n_low, n_high)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user