diff options
author | Rob Dennis <rdennis@gmail.com> | 2014-03-12 22:19:40 -0400 |
---|---|---|
committer | Rob Dennis <rdennis@gmail.com> | 2014-03-12 22:19:40 -0400 |
commit | e67de2f163eb17f664f661ad76069dbafddead7e (patch) | |
tree | 1c208973ce966ce83cd7c50ca0e5c9080ada02f7 | |
parent | 2d16e07d766958fb11c21e3274ed7022ccedb9f9 (diff) | |
parent | 715b26cac0623a510bf1afe478857487aab861a1 (diff) | |
download | configobj-git-e67de2f163eb17f664f661ad76069dbafddead7e.tar.gz |
Merge pull request #41 from robdennis/master
#14 - moved over a bunch more tests
-rw-r--r-- | test_configobj.py | 202 | ||||
-rw-r--r-- | tests/conftest.py | 14 | ||||
-rw-r--r-- | tests/test_configobj.py | 88 | ||||
-rw-r--r-- | tests/test_validate.py | 163 | ||||
-rw-r--r-- | tox.ini | 3 |
5 files changed, 240 insertions, 230 deletions
diff --git a/test_configobj.py b/test_configobj.py index 00279ab..96d19b7 100644 --- a/test_configobj.py +++ b/test_configobj.py @@ -30,204 +30,16 @@ INTP_VER = sys.version_info[:2] if INTP_VER < (2, 2): raise RuntimeError("Python v.2.2 or later needed") -try: - from codecs import BOM_UTF8 -except ImportError: - # Python 2.2 does not have this - # UTF-8 - BOM_UTF8 = '\xef\xbb\xbf' +from codecs import BOM_UTF8 from configobj import * from validate import Validator, VdtValueTooSmallError -def _test_configobj(): - """ - Testing ConfigObj - - Test indentation handling - - >>> ConfigObj({'sect': {'sect': {'foo': 'bar'}}}).write() - ['[sect]', ' [[sect]]', ' foo = bar'] - >>> cfg = ['[sect]', '[[sect]]', 'foo = bar'] - >>> ConfigObj(cfg).write() == cfg - 1 - >>> cfg = ['[sect]', ' [[sect]]', ' foo = bar'] - >>> ConfigObj(cfg).write() == cfg - 1 - >>> cfg = ['[sect]', ' [[sect]]', ' foo = bar'] - >>> assert ConfigObj(cfg).write() == cfg - >>> assert ConfigObj(oneTabCfg).write() == oneTabCfg - >>> assert ConfigObj(twoTabsCfg).write() == twoTabsCfg - >>> assert ConfigObj(tabsAndSpacesCfg).write() == [s.decode('utf-8') for s in tabsAndSpacesCfg] - >>> assert ConfigObj(cfg, indent_type=chr(9)).write() == oneTabCfg - >>> assert ConfigObj(oneTabCfg, indent_type=' ').write() == cfg - """ - - def _test_validate(): """ - >>> config = ''' - ... test1=40 - ... test2=hello - ... test3=3 - ... test4=5.0 - ... [section] - ... test1=40 - ... test2=hello - ... test3=3 - ... test4=5.0 - ... [[sub section]] - ... test1=40 - ... test2=hello - ... test3=3 - ... test4=5.0 - ... '''.split('\\n') - >>> configspec = ''' - ... test1= integer(30,50) - ... test2= string - ... test3=integer - ... test4=float(6.0) - ... [section ] - ... test1=integer(30,50) - ... test2=string - ... test3=integer - ... test4=float(6.0) - ... [[sub section]] - ... test1=integer(30,50) - ... test2=string - ... test3=integer - ... test4=float(6.0) - ... '''.split('\\n') >>> val = Validator() - >>> c1 = ConfigObj(config, configspec=configspec) - >>> test = c1.validate(val) - >>> test == { - ... 'test1': True, - ... 'test2': True, - ... 'test3': True, - ... 'test4': False, - ... 'section': { - ... 'test1': True, - ... 'test2': True, - ... 'test3': True, - ... 'test4': False, - ... 'sub section': { - ... 'test1': True, - ... 'test2': True, - ... 'test3': True, - ... 'test4': False, - ... }, - ... }, - ... } - 1 - >>> val.check(c1.configspec['test4'], c1['test4']) - Traceback (most recent call last): - VdtValueTooSmallError: the value "5.0" is too small. - - >>> val_test_config = ''' - ... key = 0 - ... key2 = 1.1 - ... [section] - ... key = some text - ... key2 = 1.1, 3.0, 17, 6.8 - ... [[sub-section]] - ... key = option1 - ... key2 = True'''.split('\\n') - >>> val_test_configspec = ''' - ... key = integer - ... key2 = float - ... [section] - ... key = string - ... key2 = float_list(4) - ... [[sub-section]] - ... key = option(option1, option2) - ... key2 = boolean'''.split('\\n') - >>> val_test = ConfigObj(val_test_config, configspec=val_test_configspec) - >>> val_test.validate(val) - 1 - >>> val_test['key'] = 'text not a digit' - >>> val_res = val_test.validate(val) - >>> val_res == {'key2': True, 'section': True, 'key': False} - 1 - >>> configspec = ''' - ... test1=integer(30,50, default=40) - ... test2=string(default="hello") - ... test3=integer(default=3) - ... test4=float(6.0, default=6.0) - ... [section ] - ... test1=integer(30,50, default=40) - ... test2=string(default="hello") - ... test3=integer(default=3) - ... test4=float(6.0, default=6.0) - ... [[sub section]] - ... test1=integer(30,50, default=40) - ... test2=string(default="hello") - ... test3=integer(default=3) - ... test4=float(6.0, default=6.0) - ... '''.split('\\n') - >>> default_test = ConfigObj(['test1=30'], configspec=configspec) - >>> default_test - ConfigObj({'test1': '30'}) - >>> default_test.defaults - [] - >>> default_test.default_values - {} - >>> default_test.validate(val) - 1 - >>> default_test == { - ... 'test1': 30, - ... 'test2': 'hello', - ... 'test3': 3, - ... 'test4': 6.0, - ... 'section': { - ... 'test1': 40, - ... 'test2': 'hello', - ... 'test3': 3, - ... 'test4': 6.0, - ... 'sub section': { - ... 'test1': 40, - ... 'test3': 3, - ... 'test2': 'hello', - ... 'test4': 6.0, - ... }, - ... }, - ... } - 1 - >>> default_test.defaults - ['test2', 'test3', 'test4'] - >>> default_test.default_values == {'test1': 40, 'test2': 'hello', - ... 'test3': 3, 'test4': 6.0} - 1 - >>> default_test.restore_default('test1') - 40 - >>> default_test['test1'] - 40 - >>> 'test1' in default_test.defaults - 1 - >>> def change(section, key): - ... section[key] = 3 - >>> _ = default_test.walk(change) - >>> default_test['section']['sub section']['test4'] - 3 - >>> default_test.restore_defaults() - >>> default_test == { - ... 'test1': 40, - ... 'test2': "hello", - ... 'test3': 3, - ... 'test4': 6.0, - ... 'section': { - ... 'test1': 40, - ... 'test2': "hello", - ... 'test3': 3, - ... 'test4': 6.0, - ... 'sub section': { - ... 'test1': 40, - ... 'test2': "hello", - ... 'test3': 3, - ... 'test4': 6.0 - ... }}} - 1 + >>> a = ['foo = fish'] >>> b = ['foo = integer(default=3)'] >>> c = ConfigObj(a, configspec=b) @@ -1230,9 +1042,9 @@ if __name__ == '__main__': # # these cannot be put among the doctests, because the doctest module # does a string.expandtabs() on all of them, sigh - oneTabCfg = ['[sect]', '\t[[sect]]', '\t\tfoo = bar'] - twoTabsCfg = ['[sect]', '\t\t[[sect]]', '\t\t\t\tfoo = bar'] - tabsAndSpacesCfg = [b'[sect]', b'\t \t [[sect]]', b'\t \t \t \t foo = bar'] + # oneTabCfg = ['[sect]', '\t[[sect]]', '\t\tfoo = bar'] + # twoTabsCfg = ['[sect]', '\t\t[[sect]]', '\t\t\t\tfoo = bar'] + # tabsAndSpacesCfg = [b'[sect]', b'\t \t [[sect]]', b'\t \t \t \t foo = bar'] # import doctest m = sys.modules.get('__main__') @@ -1240,9 +1052,7 @@ if __name__ == '__main__': a = ConfigObj(testconfig1.split('\n'), raise_errors=True) b = ConfigObj(testconfig2.split(b'\n'), raise_errors=True) i = ConfigObj(testconfig6.split(b'\n'), raise_errors=True) - globs.update({'INTP_VER': INTP_VER, 'a': a, 'b': b, 'i': i, - 'oneTabCfg': oneTabCfg, 'twoTabsCfg': twoTabsCfg, - 'tabsAndSpacesCfg': tabsAndSpacesCfg}) + globs.update({'INTP_VER': INTP_VER, 'a': a, 'b': b, 'i': i}) pre_failures, pre_tests = doctest.testmod( m, globs=globs, optionflags=doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..e11ad40 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,14 @@ +# coding=utf-8 +import pytest + +from configobj import ConfigObj +from validate import Validator + +@pytest.fixture +def empty_cfg(): + return ConfigObj() + + +@pytest.fixture +def val(): + return Validator() diff --git a/tests/test_configobj.py b/tests/test_configobj.py index d8a1140..f4f9a31 100644 --- a/tests/test_configobj.py +++ b/tests/test_configobj.py @@ -1,3 +1,4 @@ +# coding=utf-8 import os from codecs import BOM_UTF8 from warnings import catch_warnings @@ -131,16 +132,6 @@ test = some string @pytest.fixture -def cfg(): - return ConfigObj() - - -@pytest.fixture -def val(): - return Validator() - - -@pytest.fixture def testconfig1(): """ copied from the main doctest @@ -218,7 +209,6 @@ def testconfig6(): ''' - @pytest.fixture def a(testconfig1): """ @@ -528,36 +518,36 @@ class TestUnrepr(object): class TestValueErrors(object): - def test_bool(self, cfg): - cfg['a'] = 'fish' + def test_bool(self, empty_cfg): + empty_cfg['a'] = 'fish' with pytest.raises(ValueError) as excinfo: - cfg.as_bool('a') + empty_cfg.as_bool('a') assert str(excinfo.value) == 'Value "fish" is neither True nor False' - cfg['b'] = 'True' - assert cfg.as_bool('b') is True - cfg['b'] = 'off' - assert cfg.as_bool('b') is False + empty_cfg['b'] = 'True' + assert empty_cfg.as_bool('b') is True + empty_cfg['b'] = 'off' + assert empty_cfg.as_bool('b') is False - def test_int(self, cfg): + def test_int(self, empty_cfg): for bad in ('fish', '3.2'): - cfg['a'] = bad + empty_cfg['a'] = bad with pytest.raises(ValueError) as excinfo: - cfg.as_int('a') + empty_cfg.as_int('a') assert str(excinfo.value).startswith('invalid literal for int()') - cfg['b'] = '1' - assert cfg.as_bool('b') is True - cfg['b'] = '3.2' + empty_cfg['b'] = '1' + assert empty_cfg.as_bool('b') is True + empty_cfg['b'] = '3.2' - def test_float(self, cfg): - cfg['a'] = 'fish' + def test_float(self, empty_cfg): + empty_cfg['a'] = 'fish' with pytest.raises(ValueError): - cfg.as_float('a') + empty_cfg.as_float('a') - cfg['b'] = '1' - assert cfg.as_float('b') == 1 - cfg['b'] = '3.2' - assert cfg.as_float('b') == 3.2 + empty_cfg['b'] = '1' + assert empty_cfg.as_float('b') == 1 + empty_cfg['b'] = '3.2' + assert empty_cfg.as_float('b') == 3.2 @@ -886,11 +876,11 @@ class TestQuotes(object): """ tests what happens whn dealing with quotes """ - def assert_bad_quote_message(self, cfg, to_quote, **kwargs): + def assert_bad_quote_message(self, empty_cfg, to_quote, **kwargs): #TODO: this should be use repr instead of str message = 'Value "{0}" cannot be safely quoted.' with pytest.raises(ConfigObjError) as excinfo: - cfg._quote(to_quote, **kwargs) + empty_cfg._quote(to_quote, **kwargs) assert str(excinfo.value) == message.format(to_quote) def test_handle_unbalanced(self, i): @@ -1084,3 +1074,35 @@ def test_interpolation_using_default_sections(): c['DEFAULT'] = {'a' : 'fish'} c['a'] = '%(a)s' assert c.write() == ['a = %(a)s', '[DEFAULT]', 'a = fish'] + + +class TestIndentation(object): + @pytest.fixture + def max_tabbed_cfg(self): + return ['[sect]', ' [[sect]]', ' foo = bar'] + + def test_write_dictionary(self): + assert ConfigObj({'sect': {'sect': {'foo': 'bar'}}}).write() == [ + '[sect]', ' [[sect]]', ' foo = bar' + ] + + def test_indentation_preserved(self, max_tabbed_cfg): + for cfg_content in ( + ['[sect]', '[[sect]]', 'foo = bar'], + ['[sect]', ' [[sect]]', ' foo = bar'], + max_tabbed_cfg + ): + assert ConfigObj(cfg_content).write() == cfg_content + + def test_handle_tabs_vs_spaces(self, max_tabbed_cfg): + one_tab = ['[sect]', '\t[[sect]]', '\t\tfoo = bar'] + two_tabs = ['[sect]', '\t\t[[sect]]', '\t\t\t\tfoo = bar'] + tabs_and_spaces = [b'[sect]', b'\t \t [[sect]]', + b'\t \t \t \t foo = bar'] + + assert ConfigObj(one_tab).write() == one_tab + assert ConfigObj(two_tabs).write() == two_tabs + assert ConfigObj(tabs_and_spaces).write() == [s.decode('utf-8') for s in tabs_and_spaces] + assert ConfigObj(max_tabbed_cfg, indent_type=chr(9)).write() == one_tab + assert ConfigObj(one_tab, indent_type=' ').write() == max_tabbed_cfg + diff --git a/tests/test_validate.py b/tests/test_validate.py new file mode 100644 index 0000000..bffb0dc --- /dev/null +++ b/tests/test_validate.py @@ -0,0 +1,163 @@ +# coding=utf-8 + +from configobj import ConfigObj +import pytest +from validate import Validator, VdtValueTooSmallError + + +class TestBasic(object): + def test_values_too_small(self, val): + config = ''' + test1=40 + test2=hello + test3=3 + test4=5.0 + [section] + test1=40 + test2=hello + test3=3 + test4=5.0 + [[sub section]] + test1=40 + test2=hello + test3=3 + test4=5.0 + '''.splitlines() + configspec = ''' + test1= integer(30,50) + test2= string + test3=integer + test4=float(6.0) + [section ] + test1=integer(30,50) + test2=string + test3=integer + test4=float(6.0) + [[sub section]] + test1=integer(30,50) + test2=string + test3=integer + test4=float(6.0) + '''.splitlines() + c1 = ConfigObj(config, configspec=configspec) + test = c1.validate(val) + assert test == { + 'test1': True, + 'test2': True, + 'test3': True, + 'test4': False, + 'section': { + 'test1': True, + 'test2': True, + 'test3': True, + 'test4': False, + 'sub section': { + 'test1': True, + 'test2': True, + 'test3': True, + 'test4': False, + }, + }, + } + + with pytest.raises(VdtValueTooSmallError) as excinfo: + val.check(c1.configspec['test4'], c1['test4']) + assert str(excinfo.value) == 'the value "5.0" is too small.' + + def test_values(self, val): + val_test_config = ''' + key = 0 + key2 = 1.1 + [section] + key = some text + key2 = 1.1, 3.0, 17, 6.8 + [[sub-section]] + key = option1 + key2 = True'''.splitlines() + val_test_configspec = ''' + key = integer + key2 = float + [section] + key = string + key2 = float_list(4) + [[sub-section]] + key = option(option1, option2) + key2 = boolean'''.splitlines() + val_test = ConfigObj(val_test_config, configspec=val_test_configspec) + assert val_test.validate(val) + val_test['key'] = 'text not a digit' + val_res = val_test.validate(val) + assert val_res == {'key2': True, 'section': True, 'key': False} + + def test_defaults(self, val): + configspec = ''' + test1=integer(30,50, default=40) + test2=string(default="hello") + test3=integer(default=3) + test4=float(6.0, default=6.0) + [section ] + test1=integer(30,50, default=40) + test2=string(default="hello") + test3=integer(default=3) + test4=float(6.0, default=6.0) + [[sub section]] + test1=integer(30,50, default=40) + test2=string(default="hello") + test3=integer(default=3) + test4=float(6.0, default=6.0) + '''.splitlines() + default_test = ConfigObj(['test1=30'], configspec=configspec) + assert repr(default_test) == "ConfigObj({'test1': '30'})" + assert default_test.defaults == [] + assert default_test.default_values == {} + assert default_test.validate(val) + assert default_test == { + 'test1': 30, + 'test2': 'hello', + 'test3': 3, + 'test4': 6.0, + 'section': { + 'test1': 40, + 'test2': 'hello', + 'test3': 3, + 'test4': 6.0, + 'sub section': { + 'test1': 40, + 'test3': 3, + 'test2': 'hello', + 'test4': 6.0, + }, + }, + } + + assert default_test.defaults == ['test2', 'test3', 'test4'] + assert default_test.default_values == { + 'test1': 40, 'test2': 'hello', + 'test3': 3, 'test4': 6.0 + } + assert default_test.restore_default('test1') == 40 + assert default_test['test1'] == 40 + assert 'test1' in default_test.defaults + + def change(section, key): + section[key] = 3 + default_test.walk(change) + assert default_test['section']['sub section']['test4'] == 3 + + default_test.restore_defaults() + assert default_test == { + 'test1': 40, + 'test2': "hello", + 'test3': 3, + 'test4': 6.0, + 'section': { + 'test1': 40, + 'test2': "hello", + 'test3': 3, + 'test4': 6.0, + 'sub section': { + 'test1': 40, + 'test2': "hello", + 'test3': 3, + 'test4': 6.0 + }}} @@ -8,4 +8,5 @@ setenv = PYTHONWARNINGS = always commands=python test_configobj.py python validate.py - py.test tests --cov-report term-missing --cov configobj.py --cov validate.py + coverage run --source=configobj.py,validate.py -m py.test tests + coverage report |