Skip to content
Snippets Groups Projects
Commit 2cc2ce72 authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

TEST: unit tests for config module

parent fed61214
No related branches found
No related tags found
1 merge request!3BIP configuration system
#!/usr/bin/env python
#
# Utility functions available for use by tests.
#
import contextlib
import os
import os.path as op
import tempfile
def touch(fpath):
with open(fpath, 'wt') as f:
f.write(fpath)
@contextlib.contextmanager
def tempdir():
prevdir = os.getcwd()
with tempfile.TemporaryDirectory() as td:
os.chdir(td)
try:
yield td
finally:
os.chdir(prevdir)
@contextlib.contextmanager
def mock_directory(contents):
with tempdir() as td:
for c in contents:
touch(c)
yield td
def dicts_equal(da, db):
da = {k : da[k] for k in sorted(da.keys())}
db = {k : db[k] for k in sorted(db.keys())}
print(da)
print(db)
return da == db
#!/usr/bin/env python
import os.path as op
import textwrap as tw
import unittest
import pytest
import bip.utils.config as config
from bip.tests import touch, tempdir, mock_directory, dicts_equal
def test_nested_lookup():
# (dictionary, key, expected_value)
tests = [
({'a' : {'b' : {'c' : {'d' : 'e'}}}}, ['a'],
{'b' : {'c' : {'d' : 'e'}}}),
({'a' : {'b' : {'c' : {'d' : 'e'}}}}, ['a', 'b'],
{'c' : {'d' : 'e'}}),
({'a' : {'b' : {'c' : {'d' : 'e'}}}}, ['a', 'b', 'c'],
{'d' : 'e'}),
({'a' : {'b' : {'c' : {'d' : 'e'}}}}, ['a', 'b', 'c', 'd'],
'e'),
]
for d, k, exp in tests:
assert config.nested_lookup(d, k) == exp
def test_flatten_dictionary():
# (indict, nlevels, expdict)
tests = [
({'a' : {'b' : 'c', 'd' : 'e'}}, 1,
{'a_b' : 'c', 'a_d' : 'e'}),
({'a' : 'b', 'c' : {'d' : 'e', 'f' : 'g'}}, 1,
{'a' : 'b', 'c_d' : 'e', 'c_f' : 'g'}),
({'a' : 'b', 'c' : {'d' : 'e', 'f' : {'g' : 'h', 'i' : 'j'}}}, 1,
{'a' : 'b', 'c_d' : 'e', 'c_f' : {'g' : 'h', 'i' : 'j'}}),
({'a' : 'b', 'c' : {'d' : 'e', 'f' : {'g' : 'h', 'i' : 'j'}}}, 2,
{'a' : 'b', 'c_d' : 'e', 'c_f_g' : 'h', 'c_f_i' : 'j'}),
]
for indict, nlevels, expdict in tests:
assert config.flatten_dictionary(indict, nlevels) == expdict
def test_parse_override_value():
# (template value, input value, expected)
tests = [
('a', 'b', 'b'),
(None, 'b', 'b'),
(1, '1', 1),
(1.5, '1', 1),
(1, '1.5', 1.5),
(1.5, '1.5', 1.5),
(True, 'false', False),
(True, 'true', True),
([], '[1,2,3,4]', [1, 2, 3, 4]),
({}, '{"a" = 1, "b" = 2}', {'a' : 1, 'b' : 2})
]
for origval, val, expect in tests:
assert config.parse_override_value('param', origval, val) == expect
def test_Config_config_file_identifier():
# (filename, expected)
tests = [
('config.toml', 'config'),
('T1_struct.toml', 'T1_struct'),
('01.T1_struct.toml', 'T1_struct'),
('01.02.T1_struct.toml', 'T1_struct'),
]
for filename, expected in tests:
assert config.Config.config_file_identifier(filename) == expected
def test_Config_list_config_files():
contents = ['config.toml', 'config.json', 'config.cfg',
'abcde.toml', 'bcdef.toml', 'cdefg.toml',
'02.defgh.toml', 'some_file.json']
# files should be in alphabetical
# order, with config.toml last
expect = ['02.defgh.toml', 'abcde.toml', 'bcdef.toml',
'cdefg.toml', 'config.toml']
with mock_directory(contents) as mdir:
expect = [op.join(e) for e in expect]
assert config.Config.list_config_files(mdir)
def test_Config_resolve_selectors():
indict1 = {'param1' : '1',
'param2' : '2',
'subject' : {'12345' : {'param1' : '3', 'param2' : '4'},
'56789' : {'param1' : '5', 'param2' : '6'}}}
indict2 = {'param1' : '1',
'param2' : '2',
'subject' : {'12345' : {'param1' : '3',
'visit' : {'2' : {'param1' : '3.2',
'param2' : '4.2'}}},
'56789' : {'param1' : '5',
'visit' : {'2' : {'param1' : '5.2',
'param2' : '6.2'}}}}}
# (input dict, selectors, expected output)
tests = [
(indict1, {}, {'param1' : '1', 'param2' : '2'}),
(indict1, {'subject' : '12345'}, {'param1' : '3', 'param2' : '4'}),
(indict1, {'subject' : '56789'}, {'param1' : '5', 'param2' : '6'}),
(indict2, {}, {'param1' : '1', 'param2' : '2'}),
(indict2, {'subject' : '12345'}, {'param1' : '3', 'param2' : '2'}),
(indict2, {'subject' : '56789'}, {'param1' : '5', 'param2' : '2'}),
(indict2, {'visit' : '2'}, {'param1' : '1', 'param2' : '2'}),
(indict2, {'subject' : '12345',
'visit' : '1'}, {'param1' : '3', 'param2' : '2'}),
(indict2, {'subject' : '56789',
'visit' : '1'}, {'param1' : '5', 'param2' : '2'}),
(indict2, {'subject' : '12345',
'visit' : '2'}, {'param1' : '3.2', 'param2' : '4.2'}),
(indict2, {'subject' : '56789',
'visit' : '2'}, {'param1' : '5.2', 'param2' : '6.2'}),
]
for indict, selectors, expdict in tests:
result = config.Config.resolve_selectors(indict, selectors)
for k, v in expdict.items():
assert result[k] == v
def test_Config_load_config_file():
configtoml = tw.dedent("""
param1 = 1
param2 = 2
subject.12345.param1 = 3
subject.56789.param1 = 5
subject.12345.visit.2.param1 = 3.2
subject.12345.visit.2.param2 = 4.2
subject.56789.visit.2.param1 = 5.2
subject.56789.visit.2.param2 = 6.2
""").strip()
# (selectors, expected output)
tests = [
({}, {'param1' : 1, 'param2' : 2}),
({'subject' : '12345'}, {'param1' : 3, 'param2' : 2}),
({'subject' : '56789'}, {'param1' : 5, 'param2' : 2}),
({'visit' : '2'}, {'param1' : 1, 'param2' : 2}),
({'subject' : '12345',
'visit' : '1'}, {'param1' : 3, 'param2' : 2}),
({'subject' : '56789',
'visit' : '1'}, {'param1' : 5, 'param2' : 2}),
({'subject' : '12345',
'visit' : '2'}, {'param1' : 3.2, 'param2' : 4.2}),
({'subject' : '56789',
'visit' : '2'}, {'param1' : 5.2, 'param2' : 6.2}),
]
with tempdir():
fnames = ['config.toml', 'abc.toml']
for fname in fnames:
open(fname, 'wt').write(configtoml)
for selectors, expect in tests:
result = config.Config.load_config_file(fname, selectors)
for k, v in expect.items():
if fname != 'config.toml':
ident = config.Config.config_file_identifier(fname)
k = f'{ident}_{k}'
assert result[k] == v
def test_Config_load_config_file_main_relabelling():
configtoml = tw.dedent("""
param1 = 1
param2 = 2
[abc]
param3 = 3
param4 = 4
[def]
param5 = 5
param6 = 6
""").strip()
expect = {
'param1' : 1,
'param2' : 2,
'abc_param3' : 3,
'abc_param4' : 4,
'def_param5' : 5,
'def_param6' : 6
}
with tempdir():
open('config.toml', 'wt').write(configtoml)
result = config.Config.load_config_file('config.toml')
assert result == expect
def test_Config_create():
configtoml = tw.dedent("""
param1 = 0.5
abc_param1 = 0.4
def_param1 = 0.3
""").strip()
abctoml = tw.dedent("""
param1 = 0.6
param2 = 0.7
""").strip()
def01toml = tw.dedent("""
param1 = 0.8
param2 = 0.9
""").strip()
def02toml = tw.dedent("""
param1 = 1.0
param2 = 1.1
""").strip()
exp = {
'param1' : 0.5,
'abc_param1' : 0.4,
'def_param1' : 0.3,
'abc_param2' : 0.7,
'def_param2' : 1.1,
}
with tempdir():
open('config.toml', 'wt').write(configtoml)
open('abc.toml', 'wt').write(abctoml)
open('01.def.toml', 'wt').write(def01toml)
open('02.def.toml', 'wt').write(def02toml)
cfg = config.Config('.')
for k, v in exp.items():
assert cfg[k] == v
def test_Config_overrides():
configtoml = tw.dedent("""
param1 = 1
param2 = 'abc'
param3 = [1, 2, 3]
[abc]
param1 = true
param2 = 0.4
""").strip()
# (overrides, expected)
pass_tests = [
({},
{'param1' : 1,
'param2' : 'abc',
'param3' : [1, 2, 3],
'abc_param1' : True,
'abc_param2' : 0.4}),
({'param2' : 'def',
'abc_param2' : '0.7'},
{'param1' : 1,
'param2' : 'def',
'param3' : [1, 2, 3],
'abc_param1' : True,
'abc_param2' : 0.7}),
({'param1' : '8',
'abc_param1' : 'false'},
{'param1' : 8,
'param2' : 'abc',
'param3' : [1, 2, 3],
'abc_param1' : False,
'abc_param2' : 0.4}),
({'param4' : 'ghi',
'param5' : '[1,2,3,4]',
'abc_param3' : '7.5'},
{'param1' : 1,
'param2' : 'abc',
'param3' : [1, 2, 3],
'param4' : 'ghi',
'param5' : [1, 2, 3, 4],
'abc_param1' : True,
'abc_param2' : 0.4,
'abc_param3' : 7.5}),
]
# Overrides should be rejected when
# their type (as inferred by tomllib
# parsing) does not match the type of
# the stored value.
fail_tests = [
{'param1' : 'abc'},
{'param3' : '1.5'},
{'abc_param1' : 'abc'},
{'abc_param2' : 'abc'},
]
with tempdir():
open('config.toml', 'wt').write(configtoml)
for overrides, expected in pass_tests:
cfg = config.Config('.', overrides=overrides)
assert dicts_equal(cfg, expected)
for overrides in fail_tests:
with pytest.raises(ValueError):
config.Config('.', overrides=overrides)
def test_Config_access():
pass
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment