def test_validate_member_type_scheme_conflict(self): """Validate the ListOption when both member_type and member_scheme are defined.""" opt = scheme.ListOption( name='test-opt', member_type=int, member_scheme=scheme.Scheme() ) with pytest.raises(errors.SchemeValidationError): opt.validate('foo', [1, 2, 3])
def test_init_simple(self): """Initialize a ListOption.""" opt = scheme.ListOption('test-opt') assert opt.name == 'test-opt' assert type(opt.default) == scheme.NoDefault assert opt.member_type is None assert opt.member_scheme is None assert opt.bind_env is False
def test_init_full(self): """Initialize a ListOption.""" opt = scheme.ListOption( name='test-opt', default='foo', member_type=dict, member_scheme=scheme.Scheme(), bind_env=True ) assert opt.name == 'test-opt' assert type(opt.default) != scheme.NoDefault assert opt.default == 'foo' assert opt.member_type == dict assert isinstance(opt.member_scheme, scheme.Scheme) assert opt.bind_env is True
class TestScheme: """Tests for the `Scheme` class.""" def test_empty_init(self): """Initialize a Scheme with no arguments.""" sch = scheme.Scheme() assert len(sch.args) == 0 assert sch._flat is None def test_single_arg_init(self): """Initialize a Scheme with one argument.""" sch = scheme.Scheme( 'item' ) assert len(sch.args) == 1 assert sch._flat is None def test_multi_arg_init(self): """Initialize a Scheme with multiple arguments.""" sch = scheme.Scheme( 'item-1', 'item-2', 'item-3' ) assert len(sch.args) == 3 assert sch._flat is None @pytest.mark.parametrize( 'args,expected', [ ( # args (scheme.Option('foo', default='bar'),), # expected {'foo': 'bar'} ), ( # args ( scheme.Option('foo'), scheme.Option('bar', default='baz'), scheme.ListOption('list', default=['a', 'b']) ), # expected { 'bar': 'baz', 'list': ['a', 'b'] } ), ( # args ( scheme.Option('foo', default='bar'), scheme.DictOption('bar', scheme=None) ), # expected { 'foo': 'bar' } ), ( # args ( scheme.DictOption('foo', scheme=scheme.Scheme(), default={}), scheme.DictOption('bar', scheme=scheme.Scheme( scheme.Option('test', default=True), scheme.Option('data', default=None), scheme.Option('value', default=20), scheme.Option('float', default=10.1010), scheme.Option('no_default'), scheme.DictOption('dct', scheme=scheme.Scheme( scheme.Option('nested', default='here') )) )) ), # expected { 'foo': {}, 'bar': { 'test': True, 'data': None, 'value': 20, 'float': 10.1010, 'dct': { 'nested': 'here' } } } ), ] ) def test_build_defaults(self, args, expected): """Build a defaults dict from a Scheme.""" sch = scheme.Scheme(*args) defaults = sch.build_defaults() assert defaults == expected @pytest.mark.parametrize( 'args', [ ('a', 'b'), # not an instance of _BaseOpt ] ) def test_build_defaults_failure(self, args): """Build a defaults dict from a Scheme with bad data.""" sch = scheme.Scheme(*args) with pytest.raises(errors.InvalidSchemeError): sch.build_defaults() @pytest.mark.parametrize( 'args,expected', [ ( (scheme.Option('foo'),), ['foo'] ), ( (scheme.Option('foo'), scheme.Option('bar')), ['foo', 'bar'] ), ( (scheme.Option('foo'), scheme.DictOption('bar', scheme=None)), ['foo', 'bar'] ), ( ( scheme.Option('foo'), scheme.DictOption('bar', scheme=scheme.Scheme( scheme.Option('test'), scheme.DictOption('dct', scheme=scheme.Scheme( scheme.Option('nested') )), scheme.ListOption('list') )) ), ['foo', 'bar', 'bar.test', 'bar.dct', 'bar.list', 'bar.dct.nested'] ) ] ) def test_flatten(self, args, expected): """Flatten a Scheme.""" sch = scheme.Scheme(*args) flattened = sch.flatten() assert len(flattened) == len(expected) for key in expected: assert key in flattened @pytest.mark.parametrize( 'args,value', [ ( # option exists in config (scheme.Option('foo', default='bar', field_type=str),), {'foo': 'baz'} ), ( # option does not exist in config and has default, but is not required (scheme.Option('foo', default='bar', required=False, field_type=str),), {} ), ( # multiple args ( scheme.Option('foo', field_type=str), scheme.Option('bar', field_type=int), scheme.Option('baz', choices=['test']) ), {'foo': 'a', 'bar': 1, 'baz': 'test'} ), ( # optional parent option not specified, required child option # not specified ( scheme.DictOption('foo', required=False, scheme=scheme.Scheme( scheme.Option('bar', field_type=str), scheme.Option('baz', field_type=str), )), ), {} ) ] ) def test_validate_ok(self, args, value): """Validate a Scheme successfully.""" sch = scheme.Scheme(*args) sch.validate(value) @pytest.mark.parametrize( 'args,value', [ ( # option does not exist in config, no default (scheme.Option('foo', field_type=str),), {} ), ( # option exists in config, fails validation (scheme.Option('foo', default='bar', field_type=str),), {'foo': 1} ), ( # multiple args, one fails validation ( scheme.Option('foo', field_type=str), scheme.Option('bar', field_type=int), scheme.Option('baz', choices=['test']) ), {'foo': 'a', 'bar': 1, 'baz': 'something'} ), ( # optional parent option specified, required child option # not specified ( scheme.DictOption('foo', required=True, scheme=scheme.Scheme( scheme.Option('bar', field_type=str), scheme.Option('baz', field_type=str), )), ), {'foo': {'baz': 2}} ) ] ) def test_validate_failure(self, args, value): """Validate a Scheme unsuccessfully.""" sch = scheme.Scheme(*args) with pytest.raises(errors.SchemeValidationError): sch.validate(value) @pytest.mark.parametrize( 'value', [ 'foo', 1, 1.23, ['a', 'b', 'c'], {'a', 'b', 'c'}, ('a', 'b', 'c'), None, False, True ] ) def test_validate_failure_bad_config(self, value): """Validate a Scheme where the given config is not a dict.""" sch = scheme.Scheme() with pytest.raises(errors.SchemeValidationError): sch.validate(value) @pytest.mark.parametrize( 'args,value', [ ( # option does not exist in config, has default, not required (scheme.Option('foo', default='bar'),), {} ), ( # option does not exist in config, has default, not required ( scheme.DictOption('foo', scheme=scheme.Scheme( scheme.Option('bar', default=1), scheme.Option('baz'), )), ), {'foo': {'baz': 2}} ), ( # option does not exist in config, has default, not required ( scheme.ListOption('foo', member_scheme=scheme.Scheme( scheme.Option('bar', default=1), scheme.Option('baz'), )), ), {'foo': [{'baz': 2}, {'bar': 3, 'baz': 2}]} ), ] ) def test_validate_has_default(self, args, value): """Validate a Scheme where a default value is set, and the required field may or may not be set. If a default value is provided, it should be assumed to not be required. """ sch = scheme.Scheme(*args) sch.validate(value)
def test_validate_member_scheme_not_a_scheme(self): """Validate the ListOption, where the member_scheme is not a Scheme.""" opt = scheme.ListOption('test-opt', member_scheme='not-none-or-scheme') with pytest.raises(errors.SchemeValidationError): opt.validate('foo', ['a', 'b', 'c'])
def test_validate_member_scheme_fail(self, member_scheme, value): """Validate the ListOption, where member_scheme validation fails.""" opt = scheme.ListOption('test-opt', member_scheme=member_scheme) with pytest.raises(errors.SchemeValidationError): opt.validate('foo', value)
def test_validate_member_scheme_ok(self, member_scheme, value): """Validate the ListOption, where member_scheme validation succeeds.""" opt = scheme.ListOption('test-opt', member_scheme=member_scheme) opt.validate('foo', value)
def test_validate_bad_data(self, value): """Validate when the value is not a list""" opt = scheme.ListOption('test-opt') with pytest.raises(errors.SchemeValidationError): opt.validate('foo', value)
class TestListOption: """Tests for the `ListOption` class.""" def test_init_simple(self): """Initialize a ListOption.""" opt = scheme.ListOption('test-opt') assert opt.name == 'test-opt' assert type(opt.default) == scheme.NoDefault assert opt.member_type is None assert opt.member_scheme is None assert opt.bind_env is False def test_init_full(self): """Initialize a ListOption.""" opt = scheme.ListOption( name='test-opt', default='foo', member_type=dict, member_scheme=scheme.Scheme(), bind_env=True ) assert opt.name == 'test-opt' assert type(opt.default) != scheme.NoDefault assert opt.default == 'foo' assert opt.member_type == dict assert isinstance(opt.member_scheme, scheme.Scheme) assert opt.bind_env is True @pytest.mark.parametrize( 'value', [ 'foo', 1, 1.234, False, True, None, {'a': 1, 'b': 2}, ('foo', 'bar'), {1, 2, 3} ] ) def test_validate_bad_data(self, value): """Validate when the value is not a list""" opt = scheme.ListOption('test-opt') with pytest.raises(errors.SchemeValidationError): opt.validate('foo', value) def test_validate_member_type_scheme_conflict(self): """Validate the ListOption when both member_type and member_scheme are defined.""" opt = scheme.ListOption( name='test-opt', member_type=int, member_scheme=scheme.Scheme() ) with pytest.raises(errors.SchemeValidationError): opt.validate('foo', [1, 2, 3]) @pytest.mark.parametrize( 'member_type,value', [ (str, ['a', 'b', 'c']), (int, [1, 2, 3]), (float, [1.0, 2.0, 3.0]), (bool, [False, False, True]), (tuple, [(1,), (2,), (3,)]), (list, [[1], [2], [3]]), (dict, [{'a': 1, 'b': 2}]) ] ) def test_validate_member_type_ok(self, member_type, value): """Validate the ListOption, where member_type validation succeeds.""" opt = scheme.ListOption('test-opt', member_type=member_type) opt.validate('foo', value) @pytest.mark.parametrize( 'member_type,value', [ (str, ['a', 1]), (str, [1, 2]), (int, [1, 2, '3']), (int, ['foo', 'bar']), (float, [1.0, '2.0', 3.0]), (float, ['foo', 'bar']), (bool, ['False', False, True]), (bool, ['foo', 'bar']), (tuple, [(1,), '(2,)', (3,)]), (tuple, ['']), (list, [[1], (2,), [3]]), (list, ['foo', 'bar']), (dict, [{'a': 1}, {1, 2, 3}]), (dict, ['foo', 'bar']) ] ) def test_validate_member_type_failure(self, member_type, value): """Validate the ListOption, where member_type validation fails.""" opt = scheme.ListOption('test-opt', member_type=member_type) with pytest.raises(errors.SchemeValidationError): opt.validate('foo', value) @pytest.mark.parametrize( 'member_scheme,value', [ # an empty scheme will validate every dict as correct (scheme.Scheme(), [{'foo': 'bar'}]), (scheme.Scheme(), [{1: 3}]), (scheme.Scheme(), [{1.23: 2.31}]), (scheme.Scheme(), [{False: True}]), (scheme.Scheme(), [{None: None}]), (scheme.Scheme(), [{(1, 2): (2, 1)}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 'bar'}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 'baz'}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 'baz'}, {'foo': 'bar'}]) ] ) def test_validate_member_scheme_ok(self, member_scheme, value): """Validate the ListOption, where member_scheme validation succeeds.""" opt = scheme.ListOption('test-opt', member_scheme=member_scheme) opt.validate('foo', value) @pytest.mark.parametrize( 'member_scheme,value', [ (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 1}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 1.23}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': False}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': True}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': None}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': (1, 2)}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': ['a', 'b']}]), (scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': {'a', 'b'}}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': 'foo'}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': 1.23}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': False}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': True}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': None}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': (1, 2)}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': ['a', 'b']}]), (scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': {'a', 'b'}}]) ] ) def test_validate_member_scheme_fail(self, member_scheme, value): """Validate the ListOption, where member_scheme validation fails.""" opt = scheme.ListOption('test-opt', member_scheme=member_scheme) with pytest.raises(errors.SchemeValidationError): opt.validate('foo', value) def test_validate_member_scheme_not_a_scheme(self): """Validate the ListOption, where the member_scheme is not a Scheme.""" opt = scheme.ListOption('test-opt', member_scheme='not-none-or-scheme') with pytest.raises(errors.SchemeValidationError): opt.validate('foo', ['a', 'b', 'c']) @pytest.mark.parametrize( 'option,prefix,auto_env', [ (scheme.ListOption('foo', bind_env=False), None, False), (scheme.ListOption('foo', bind_env=False), None, True), (scheme.ListOption('foo', bind_env=False), 'TEST_ENV', False), (scheme.ListOption('foo', bind_env=False), 'TEST_ENV', True), (scheme.ListOption('foo', bind_env=True), None, False), (scheme.ListOption('foo', bind_env=True), None, True), (scheme.ListOption('foo', bind_env=True), 'TEST_ENV', False), (scheme.ListOption('foo', bind_env=True), 'TEST_ENV', True), ] ) def test_parse_env_none(self, option, prefix, auto_env): """Parse environment variables for the ListOption. All of theses tests should result in None being returned because no environment variables are actually set. """ actual = option.parse_env(prefix=prefix, auto_env=auto_env) assert actual is None @pytest.mark.parametrize( 'option,key,prefix,auto_env,expected', [ (scheme.ListOption('foo', bind_env=True), 'foo', 'TEST_ENV_', False, ['bar']), (scheme.ListOption('foo', bind_env=True), 'foo', 'TEST_ENV_', True, ['bar']), (scheme.ListOption('foo', bind_env=True), 'bar.list', 'TEST_ENV_', False, ['a', 'b', 'c']), (scheme.ListOption('foo', bind_env=True), 'bar.list', 'TEST_ENV_', True, ['a', 'b', 'c']), ] ) def test_parse_env_ok(self, option, key, prefix, auto_env, expected, with_env): """Parse environment variables for the ListOption.""" actual = option.parse_env(key=key, prefix=prefix, auto_env=auto_env) assert actual == expected