From 71f2e8c577a47997826bdbe855b811fd34cf3056 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 15 Jun 2017 13:21:33 +0200 Subject: [PATCH] None validation fixups for test_configtypes --- tests/unit/config/test_configtypes.py | 226 ++++++++------------------ 1 file changed, 69 insertions(+), 157 deletions(-) diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index 945862041..a44556a72 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -253,27 +253,30 @@ class TestBaseType: with pytest.raises(configexc.ValidationError): basetype._validate_valid_values('baz') - @pytest.mark.parametrize('val', [None, '', 'foobar', 'snowman: ☃', - 'foo bar']) - def test_basic_validation_valid(self, klass, val): + @pytest.mark.parametrize('val', ['', 'foobar', 'snowman: ☃', 'foo bar']) + def test_basic_str_validation_valid(self, klass, val): """Test _basic_validation with valid values.""" basetype = klass() basetype.none_ok = True - basetype._basic_validation(val) + basetype._basic_str_validation(val) - @pytest.mark.parametrize('val', [None, '', '\x00']) + @pytest.mark.parametrize('val', ['', '\x00']) def test_basic_validation_invalid(self, klass, val): """Test _basic_validation with invalid values.""" with pytest.raises(configexc.ValidationError): - klass()._basic_validation(val) + klass()._basic_str_validation(val) - def test_basic_validation_pytype_valid(self, klass): - klass()._basic_validation([], pytype=list) + def test_basic_py_validation_valid(self, klass): + klass()._basic_py_validation([], list) - def test_basic_validation_pytype_invalid(self, klass): + def test_basic_py_validation_invalid(self, klass): with pytest.raises(configexc.ValidationError, match='expected a value of type str but got list'): - klass()._basic_validation([], pytype=str) + klass()._basic_py_validation([], str) + + def test_basic_py_validation_invalid_str(self, klass): + with pytest.raises(configexc.ValidationError): + klass()._basic_py_validation('\x00', str) def test_complete_none(self, klass): """Test complete with valid_values not set.""" @@ -322,8 +325,6 @@ class MappingSubclass(configtypes.MappingType): class TestMappingType: TESTS = { - None: None, - '': None, 'one': 1, 'two': 2, 'ONE': 1, @@ -335,9 +336,9 @@ class TestMappingType: @pytest.mark.parametrize('val, expected', list(TESTS.items())) def test_from_py(self, klass, val, expected): - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == expected - @pytest.mark.parametrize('val', [None, 'one!', 'blah']) + @pytest.mark.parametrize('val', ['one!', 'blah']) def test_from_py_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): klass().from_py(val) @@ -369,8 +370,6 @@ class TestString: klass(minlen=minlen, maxlen=maxlen) @pytest.mark.parametrize('kwargs, val', [ - ({'none_ok': True}, ''), # Empty with none_ok - ({'none_ok': True}, None), # None with none_ok ({}, "Test! :-)"), # Forbidden chars ({'forbidden': 'xyz'}, 'fobar'), @@ -383,11 +382,9 @@ class TestString: ({'valid_values': configtypes.ValidValues('abcd')}, 'abcd'), ]) def test_from_py(self, klass, kwargs, val): - expected = None if not val else val - assert klass(**kwargs).from_py(val) == expected + assert klass(**kwargs).from_py(val) == val @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), # Empty without none_ok # Forbidden chars ({'forbidden': 'xyz'}, 'foybar'), ({'forbidden': 'xyz'}, 'foxbar'), @@ -474,10 +471,7 @@ class TestList: json_val = json.dumps(val) assert klass().from_str(json_val) == val - def test_from_str_empty(self, klass): - assert klass(none_ok_outer=True).from_str('') is None - - @pytest.mark.parametrize('val', ['', '[[', 'true']) + @pytest.mark.parametrize('val', ['[[', 'true']) def test_from_str_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): klass().from_str(val) @@ -577,11 +571,9 @@ class TestBool: 'false': False, 'FaLsE': False, 'off': False, - - '': None, } - INVALID = ['10', 'yess', 'false_', ''] + INVALID = ['10', 'yess', 'false_'] @pytest.fixture def klass(self): @@ -589,21 +581,20 @@ class TestBool: @pytest.mark.parametrize('val, expected', sorted(TESTS.items())) def test_from_str_valid(self, klass, val, expected): - assert klass(none_ok=True).from_str(val) == expected + assert klass().from_str(val) == expected @pytest.mark.parametrize('val', INVALID) def test_from_str_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): klass().from_str(val) - @pytest.mark.parametrize('val', [True, False, None]) + @pytest.mark.parametrize('val', [True, False]) def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) is val + assert klass().from_py(val) is val - @pytest.mark.parametrize('val', [None, 42]) - def test_from_py_invalid(self, klass, val): + def test_from_py_invalid(self, klass): with pytest.raises(configexc.ValidationError): - klass().from_py(val) + klass().from_py(42) class TestBoolAsk: @@ -622,21 +613,20 @@ class TestBoolAsk: @pytest.mark.parametrize('val, expected', sorted(TESTS.items())) def test_from_str_valid(self, klass, val, expected): - assert klass(none_ok=True).from_str(val) == expected + assert klass().from_str(val) == expected @pytest.mark.parametrize('val', INVALID) def test_from_str_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): klass().from_str(val) - @pytest.mark.parametrize('val', [True, False, None, 'ask']) + @pytest.mark.parametrize('val', [True, False, 'ask']) def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + assert klass().from_py(val) == val - @pytest.mark.parametrize('val', [None, 42]) - def test_from_py_invalid(self, klass, val): + def test_from_py_invalid(self, klass): with pytest.raises(configexc.ValidationError): - klass().from_py(val) + klass().from_py(42) class TestNumeric: @@ -694,14 +684,12 @@ class TestInt: @pytest.mark.parametrize('kwargs, val, expected', [ ({}, '1337', 1337), ({}, '0', 0), - ({'none_ok': True}, '', None), ({'minval': 2}, '2', 2), ]) def test_from_str_valid(self, klass, kwargs, val, expected): assert klass(**kwargs).from_str(val) == expected @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), ({}, '2.5'), ({}, 'foobar'), ({'minval': 2, 'maxval': 3}, '1'), @@ -713,14 +701,12 @@ class TestInt: @pytest.mark.parametrize('kwargs, val', [ ({}, 1337), ({}, 0), - ({'none_ok': True}, None), ({'minval': 2}, 2), ]) def test_from_py_valid(self, klass, kwargs, val): assert klass(**kwargs).from_py(val) == val @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), ({}, 2.5), ({}, 'foobar'), ({'minval': 2, 'maxval': 3}, 1), @@ -739,14 +725,12 @@ class TestFloat: @pytest.mark.parametrize('kwargs, val, expected', [ ({}, '1337', 1337), ({}, '1337.42', 1337.42), - ({'none_ok': True}, '', None), ({'minval': 2.00}, '2.00', 2.00), ]) def test_from_str_valid(self, klass, kwargs, val, expected): assert klass(**kwargs).from_str(val) == expected @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), ({}, 'foobar'), ({'minval': 2, 'maxval': 3}, '3.01'), ]) @@ -758,14 +742,12 @@ class TestFloat: ({}, 1337), ({}, 0), ({}, 1337.42), - ({'none_ok': True}, None), ({'minval': 2}, 2.01), ]) def test_from_py_valid(self, klass, kwargs, val): assert klass(**kwargs).from_py(val) == val @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), ({}, 'foobar'), ({'minval': 2, 'maxval': 3}, 1.99), ]) @@ -783,7 +765,6 @@ class TestPerc: @pytest.mark.parametrize('kwargs, val, expected', [ ({}, '1337%', 1337), ({}, '1337.42%', 1337.42), - ({'none_ok': True}, '', None), ({'maxval': 2}, '2%', 2), ]) def test_from_str_valid(self, klass, kwargs, val, expected): @@ -794,7 +775,6 @@ class TestPerc: ({}, '1337%%'), ({}, 'foobar'), ({}, 'foobar%'), - ({}, ''), ({'minval': 2}, '1%'), ({'maxval': 2}, '3%'), ({'minval': 2, 'maxval': 3}, '1%'), @@ -806,14 +786,12 @@ class TestPerc: @pytest.mark.parametrize('kwargs, val, expected', [ ({}, '1337.42%', 1337.42), - ({'none_ok': True}, None, None), ({'minval': 2}, '2.01%', 2.01), ]) def test_from_py_valid(self, klass, kwargs, val, expected): assert klass(**kwargs).from_py(val) == expected @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), ({}, 'foobar'), ({}, 23), ({'minval': 2, 'maxval': 3}, '1.99%'), @@ -842,7 +820,6 @@ class TestPercOrInt: @pytest.mark.parametrize('kwargs, val, expected', [ ({}, '1337%', '1337%'), ({}, '1337', 1337), - ({'none_ok': True}, '', None), ({'minperc': 2}, '2%', '2%'), ({'maxperc': 2}, '2%', '2%'), @@ -861,7 +838,6 @@ class TestPercOrInt: ({}, '1337%%'), ({}, '1337.42%'), ({}, 'foobar'), - ({}, ''), ({'minperc': 2}, '1%'), ({'maxperc': 2}, '3%'), @@ -877,9 +853,9 @@ class TestPercOrInt: with pytest.raises(configexc.ValidationError): klass(**kwargs).from_str(val) - @pytest.mark.parametrize('val', ['1337%', 1337, None]) + @pytest.mark.parametrize('val', ['1337%', 1337]) def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + assert klass().from_py(val) == val @pytest.mark.parametrize('val', ['1337%%', '1337']) def test_from_py_invalid(self, klass, val): @@ -901,13 +877,13 @@ class TestCommand: def klass(self): return configtypes.Command - @pytest.mark.parametrize('val', ['', 'cmd1', 'cmd2', 'cmd1 foo bar', + @pytest.mark.parametrize('val', ['cmd1', 'cmd2', 'cmd1 foo bar', 'cmd2 baz fish']) def test_from_py_valid(self, klass, val): expected = None if not val else val - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == expected - @pytest.mark.parametrize('val', ['', 'cmd3', 'cmd3 foo bar', ' ']) + @pytest.mark.parametrize('val', ['cmd3', 'cmd3 foo bar', ' ']) def test_from_py_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): klass().from_py(val) @@ -932,7 +908,6 @@ class ColorTests: ('#111222333', TYPES), ('#111122223333', TYPES), ('red', TYPES), - (None, TYPES), ('#00000G', []), ('#123456789ABCD', []), @@ -995,23 +970,14 @@ class TestColors: @pytest.mark.parametrize('klass, val', TESTS.valid) def test_from_py_valid(self, klass, val): - if not val: - expected = None - elif klass is configtypes.QtColor: - expected = QColor(val) - else: - expected = val - assert klass(none_ok=True).from_py(val) == expected + expected = QColor(val) if klass is configtypes.QtColor else val + assert klass().from_py(val) == expected @pytest.mark.parametrize('klass, val', TESTS.invalid) def test_from_py_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): klass().from_py(val) - def test_validate_invalid_empty(self, klass_fixt): - with pytest.raises(configexc.ValidationError): - klass_fixt().from_py('') - FontDesc = collections.namedtuple('FontDesc', ['style', 'weight', 'pt', 'px', 'family']) @@ -1080,15 +1046,13 @@ class TestFont: def qtfont_class(self): return configtypes.QtFont - @pytest.mark.parametrize('val, desc', sorted(TESTS.items()) + [(None, None)]) + @pytest.mark.parametrize('val, desc', sorted(TESTS.items())) def test_from_py_valid(self, klass, val, desc): - if desc is None: - expected = None - elif klass is configtypes.Font: + if klass is configtypes.Font: expected = val elif klass is configtypes.QtFont: expected = Font.fromdesc(desc) - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == expected def test_qtfont_float(self, qtfont_class): """Test QtFont's transform with a float as point size. @@ -1114,8 +1078,6 @@ class TestFont: pytest.param('green', marks=font_xfail), pytest.param('10pt', marks=font_xfail), pytest.param('10pt ""', marks=font_xfail), - '', - None, ]) def test_from_py_invalid(self, klass, val): with pytest.raises(configexc.ValidationError): @@ -1124,7 +1086,7 @@ class TestFont: class TestFontFamily: - TESTS = ['"Foobar Neue"', 'inconsolatazi4', 'Foobar', None] + TESTS = ['"Foobar Neue"', 'inconsolatazi4', 'Foobar'] INVALID = [ '10pt "Foobar Neue"', '10PT "Foobar Neue"', @@ -1140,7 +1102,6 @@ class TestFontFamily: 'oblique 10pt "Foobar Neue"', 'normal bold 10pt "Foobar Neue"', 'bold italic 10pt "Foobar Neue"', - None, # with none_ok=False ] @pytest.fixture @@ -1149,7 +1110,7 @@ class TestFontFamily: @pytest.mark.parametrize('val', TESTS) def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + assert klass().from_py(val) == val @pytest.mark.parametrize('val', INVALID) def test_from_py_invalid(self, klass, val): @@ -1166,15 +1127,12 @@ class TestRegex: @pytest.mark.parametrize('val', [ r'(foo|bar)?baz[fis]h', re.compile('foobar'), - None ]) def test_from_py_valid(self, klass, val): - expected = None if val is None else RegexEq(val) - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == RegexEq(val) @pytest.mark.parametrize('val', [ pytest.param(r'(foo|bar))?baz[fis]h', id='unmatched parens'), - pytest.param('', id='empty'), pytest.param('(' * 500, id='too many parens'), ]) def test_from_py_invalid(self, klass, val): @@ -1239,8 +1197,7 @@ class TestDict: @pytest.mark.parametrize('val', [ {"foo": "bar"}, {"foo": "bar", "baz": "fish"}, - '', # empty value with none_ok=true - {}, # ditto + {}, # with none_ok=True ]) def test_from_str_valid(self, klass, val): expected = None if not val else val @@ -1253,7 +1210,6 @@ class TestDict: @pytest.mark.parametrize('val', [ '["foo"]', # valid json but not a dict '{"hello": 23}', # non-string as value - '', # empty value with none_ok=False '[invalid', # invalid json ]) def test_from_str_invalid(self, klass, val): @@ -1293,13 +1249,6 @@ class TestFile: def file_class(self): return configtypes.File - def test_from_py_empty(self, klass): - with pytest.raises(configexc.ValidationError): - klass().from_py('') - - def test_from_py_empty_none_ok(self, klass): - assert klass(none_ok=True).from_py('') is None - def test_from_py_does_not_exist_file(self, os_mock): """Test from_py with a file which does not exist (File).""" os_mock.path.isfile.return_value = False @@ -1315,12 +1264,11 @@ class TestFile: ('/foobar', '/foobar'), ('~/foobar', '/home/foo/foobar'), ('$HOME/foobar', '/home/foo/foobar'), - ('', None), ]) def test_from_py_exists_abs(self, klass, os_mock, val, expected): """Test from_py with a file which does exist.""" os_mock.path.isfile.return_value = True - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == expected def test_from_py_exists_rel(self, klass, os_mock, monkeypatch): """Test from_py with a relative path to an existing file.""" @@ -1362,16 +1310,6 @@ class TestDirectory: def klass(self): return configtypes.Directory - def test_from_py_empty(self, klass): - """Test from_py with empty string and none_ok = False.""" - with pytest.raises(configexc.ValidationError): - klass().from_py('') - - def test_from_py_empty_none_ok(self, klass): - """Test from_py with empty string and none_ok = True.""" - t = configtypes.Directory(none_ok=True) - assert t.from_py(None) is None - def test_from_py_does_not_exist(self, klass, os_mock): """Test from_py with a directory which does not exist.""" os_mock.path.isdir.return_value = False @@ -1425,17 +1363,14 @@ class TestFormatString: @pytest.mark.parametrize('val', [ 'foo bar baz', '{foo} {bar} baz', - None, ]) def test_from_py_valid(self, typ, val): - typ.none_ok = True assert typ.from_py(val) == val @pytest.mark.parametrize('val', [ '{foo} {bar} {baz}', '{foo} {bar', '{1}', - None, ]) def test_from_py_invalid(self, typ, val): with pytest.raises(configexc.ValidationError): @@ -1449,7 +1384,6 @@ class TestShellCommand: return configtypes.ShellCommand @pytest.mark.parametrize('kwargs, val, expected', [ - ({'none_ok': True}, '', None), ({}, 'foobar', ['foobar']), ({'placeholder': '{}'}, 'foo {} bar', ['foo', '{}', 'bar']), ({'placeholder': '{}'}, 'foo{}bar', ['foo{}bar']), @@ -1461,7 +1395,6 @@ class TestShellCommand: assert cmd.from_py(expected) == expected @pytest.mark.parametrize('kwargs, val', [ - ({}, ''), ({'placeholder': '{}'}, 'foo bar'), ({'placeholder': '{}'}, 'foo { } bar'), ({}, 'foo"'), # not splittable with shlex @@ -1478,7 +1411,6 @@ class TestProxy: return configtypes.Proxy @pytest.mark.parametrize('val, expected', [ - (None, None), ('system', configtypes.SYSTEM_PROXY), ('none', QNetworkProxy(QNetworkProxy.NoProxy)), ('socks://example.com/', @@ -1492,13 +1424,12 @@ class TestProxy: pac.PACFetcher(QUrl('pac+file:///tmp/proxy.pac'))), ]) def test_from_py_valid(self, klass, val, expected): - actual = klass(none_ok=True).from_py(val) + actual = klass().from_py(val) if isinstance(actual, QNetworkProxy): actual = QNetworkProxy(actual) assert actual == expected @pytest.mark.parametrize('val', [ - '', 'blah', ':', # invalid URL 'ftp://example.com/', # invalid scheme @@ -1526,13 +1457,11 @@ class TestSearchEngineUrl: 'http://example.com/?q={}', 'http://example.com/?q={0}', 'http://example.com/?q={0}&a={0}', - None, # empty value with none_ok ]) def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + assert klass().from_py(val) == val @pytest.mark.parametrize('val', [ - '', # empty value without none_ok 'foo', # no placeholder ':{}', # invalid URL 'foo{bar}baz{}', # {bar} format string variable @@ -1551,15 +1480,13 @@ class TestFuzzyUrl: return configtypes.FuzzyUrl @pytest.mark.parametrize('val, expected', [ - (None, None), ('http://example.com/?q={}', QUrl('http://example.com/?q={}')), ('example.com', QUrl('http://example.com')), ]) def test_from_py_valid(self, klass, val, expected): - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == expected @pytest.mark.parametrize('val', [ - None, '::foo', # invalid URL 'foo bar', # invalid search term ]) @@ -1574,24 +1501,17 @@ class TestPadding: def klass(self): return configtypes.Padding - @pytest.mark.parametrize('val, expected', [ - (None, None), - ({'top': 1, 'bottom': 2, 'left': 3, 'right': 4}, - configtypes.PaddingValues(1, 2, 3, 4)), - ]) - def test_from_py_valid(self, klass, val, expected): - assert klass(none_ok=True).from_py(val) == expected + def test_from_py_valid(self, klass): + val = {'top': 1, 'bottom': 2, 'left': 3, 'right': 4} + expected = configtypes.PaddingValues(1, 2, 3, 4) + assert klass().from_py(val) == expected - @pytest.mark.parametrize('val, expected', [ - ('', None), - ('{"top": 1, "bottom": 2, "left": 3, "right": 4}', - configtypes.PaddingValues(1, 2, 3, 4)), - ]) - def test_from_str_valid(self, klass, val, expected): - assert klass(none_ok=True).from_str(val) == expected + def test_from_str_valid(self, klass): + val = '{"top": 1, "bottom": 2, "left": 3, "right": 4}' + expected = configtypes.PaddingValues(1, 2, 3, 4) + assert klass().from_str(val) == expected @pytest.mark.parametrize('val', [ - None, {'top': 1, 'bottom': 2, 'left': 3, 'right': 4, 'foo': 5}, {'top': 1, 'bottom': 2, 'left': 3, 'right': 'four'}, {'top': 1, 'bottom': 2}, @@ -1609,14 +1529,13 @@ class TestEncoding: def klass(self): return configtypes.Encoding - @pytest.mark.parametrize('val', ['utf-8', 'UTF-8', 'iso8859-1', None]) + @pytest.mark.parametrize('val', ['utf-8', 'UTF-8', 'iso8859-1']) def test_from_py(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + assert klass().from_py(val) == val - @pytest.mark.parametrize('val', ['blubber', '']) - def test_validate_invalid(self, klass, val): + def test_validate_invalid(self, klass): with pytest.raises(configexc.ValidationError): - klass().from_py(val) + klass().from_py('blubber') class TestUrl: @@ -1624,7 +1543,6 @@ class TestUrl: TESTS = { 'http://qutebrowser.org/': QUrl('http://qutebrowser.org/'), 'http://heise.de/': QUrl('http://heise.de/'), - None: None, } @pytest.fixture @@ -1633,12 +1551,11 @@ class TestUrl: @pytest.mark.parametrize('val, expected', list(TESTS.items())) def test_from_py_valid(self, klass, val, expected): - assert klass(none_ok=True).from_py(val) == expected + assert klass().from_py(val) == expected - @pytest.mark.parametrize('val', [None, '+']) - def test_from_py_invalid(self, klass, val): + def test_from_py_invalid(self, klass): with pytest.raises(configexc.ValidationError): - klass().from_py(val) + klass().from_py('+') class TestSessionName: @@ -1647,20 +1564,17 @@ class TestSessionName: def klass(self): return configtypes.SessionName - @pytest.mark.parametrize('val', [None, 'foobar']) - def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + def test_from_py_valid(self, klass): + assert klass().from_py('foobar') == 'foobar' - @pytest.mark.parametrize('val', [None, '_foo']) - def test_from_py_invalid(self, klass, val): + def test_from_py_invalid(self, klass): with pytest.raises(configexc.ValidationError): - klass().from_py(val) + klass().from_py('_foo') class TestConfirmQuit: TESTS = [ - None, ['multiple-tabs', 'downloads'], ['downloads', 'multiple-tabs'], ['downloads', None, 'multiple-tabs'], @@ -1677,7 +1591,6 @@ class TestConfirmQuit: assert cq.from_str(json.dumps(val)) == val @pytest.mark.parametrize('val', [ - None, # with none_ok=False ['foo'], ['downloads', 'foo'], # valid value mixed with invalid one ['downloads', 'multiple-tabs', 'downloads'], # duplicate value @@ -1707,14 +1620,13 @@ class TestTimestampTemplate: def klass(self): return configtypes.TimestampTemplate - @pytest.mark.parametrize('val', [None, 'foobar', '%H:%M', 'foo %H bar %M']) + @pytest.mark.parametrize('val', ['foobar', '%H:%M', 'foo %H bar %M']) def test_from_py_valid(self, klass, val): - assert klass(none_ok=True).from_py(val) == val + assert klass().from_py(val) == val - @pytest.mark.parametrize('val', [None, '%']) - def test_from_py_invalid(self, klass, val): + def test_from_py_invalid(self, klass): with pytest.raises(configexc.ValidationError): - klass().from_py(val) + klass().from_py('%') @pytest.mark.parametrize('first, second, equal', [