未验证 提交 d3d689c5 编写于 作者: C Caio Carrara

Merge remote-tracking branch 'clebergnu/tags_key_val'

Signed-off-by: NCaio Carrara <ccarrara@redhat.com>
......@@ -318,7 +318,8 @@ class Job(object):
suite = loader.filter_test_tags(
suite,
self.args.filter_by_tags,
self.args.filter_by_tags_include_empty)
self.args.filter_by_tags_include_empty,
self.args.filter_by_tags_include_empty_key)
except loader.LoaderUnhandledReferenceError as details:
raise exceptions.OptionValidationError(details)
except KeyboardInterrupt:
......
......@@ -90,7 +90,41 @@ def parse_filter_by_tags(filter_by_tags):
return result
def filter_test_tags(test_suite, filter_by_tags, include_empty=False):
def must_split_flat_key_val(must):
"""
Splits the flat and key:val tags apart
:returns: the flat set tags and the key:val tags
:rtype: tuple(set, dict)
"""
key_val = {}
flat = set()
for i in must:
if ':' in i:
k, v = i.split(':', 1)
key_val[k] = v
else:
flat.add(i)
return flat, key_val
def must_key_val_matches(must_key_vals, test_tags, include_empty_key):
"""
Checks if the required key:vals are fulfilled by the test_tags
:rtype: bool
"""
for k, v in must_key_vals.items():
if k in test_tags:
return v in test_tags[k]
else:
if include_empty_key:
return True
return False
def filter_test_tags(test_suite, filter_by_tags, include_empty=False,
include_empty_key=False):
"""
Filter the existing (unfiltered) test suite based on tags
......@@ -105,6 +139,9 @@ def filter_test_tags(test_suite, filter_by_tags, include_empty=False):
:type filter_by_tags: list of comma separated tags (['foo,bar', 'fast'])
:param include_empty: if true tests without tags will not be filtered out
:type include_empty: bool
:param include_empty_key: if true tests "keys" on key:val tags will be
included in the filtered results
:type include_empty_key: bool
"""
filtered = []
must_must_nots = parse_filter_by_tags(filter_by_tags)
......@@ -120,8 +157,15 @@ def filter_test_tags(test_suite, filter_by_tags, include_empty=False):
if must_not.intersection(test_tags):
continue
if must:
if not must.issubset(test_tags):
must_flat, must_key_val = must_split_flat_key_val(must)
if must_key_val:
if not must_key_val_matches(must_key_val,
test_tags,
include_empty_key):
continue
if must_flat:
if not must_flat.issubset(test_tags):
continue
filtered.append((klass, info))
......
......@@ -122,7 +122,8 @@ class TestLister(object):
test_suite = loader.filter_test_tags(
test_suite,
self.args.filter_by_tags,
self.args.filter_by_tags_include_empty)
self.args.filter_by_tags_include_empty,
self.args.filter_by_tags_include_empty_key)
test_matrix, stats, tag_stats = self._get_test_matrix(test_suite)
self._display(test_matrix, stats, tag_stats)
......@@ -181,6 +182,13 @@ class List(CLICmd):
'filtering. This effectively means they '
'will be kept in the test suite found '
'previously to filtering.'))
filtering.add_argument('--filter-by-tags-include-empty-key',
action='store_true', default=False,
help=('Include all tests that do not have a '
'matching key in its key:val tags. This '
'effectively means those tests will be '
'kept in the test suite found previously '
'to filtering.'))
def run(self, args):
test_lister = TestLister(args)
......
......@@ -204,6 +204,13 @@ class Run(CLICmd):
'filtering. This effectively means they '
'will be kept in the test suite found '
'previously to filtering.'))
filtering.add_argument('--filter-by-tags-include-empty-key',
action='store_true', default=False,
help=('Include all tests that do not have a '
'matching key in its key:val tags. This '
'effectively means those tests will be '
'kept in the test suite found previously '
'to filtering.'))
def run(self, args):
"""
......
......@@ -1570,6 +1570,63 @@ inclusion of tests without tags::
INSTRUMENTED perf.py:Idle.test_idle
INSTRUMENTED perf.py:Disk.test_device
Using further categorization with keys and values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All the examples given so far are limited to "flat" tags. Sometimes,
it's helpful to categorize tests with extra context. For instance, if
you have tests that are sensitive to the platform endianess, you may
way to categorize them by endianess, while at the same time,
specifying the exact type of endianess that is required.
Example::
class ByteOrder(Test):
def test_le(self):
"""
:avocado: tags=endianess:little
"""
...
def test_be(self):
"""
:avocado: tags=endianess:big
"""
...
class Generic(Test):
def test(self):
"""
:avocado: tags=generic
"""
To list tests without any type of filtering would give you::
$ avocado list byteorder.py
INSTRUMENTED byteorder.py:ByteOrder.test_le
INSTRUMENTED byteorder.py:ByteOrder.test_be
INSTRUMENTED byteorder.py:Generic.test
To list tests that are somehow related to endianess, you can use::
$ avocado list byteorder.py --filter-by-tags endianess
INSTRUMENTED byteorder.py:ByteOrder.test_le
INSTRUMENTED byteorder.py:ByteOrder.test_be
And to be even more specific, you can use::
$ avocado list byteorder.py --filter-by-tags endianess:big
INSTRUMENTED byteorder.py:ByteOrder.test_be
Now, suppose you intend to run tests on a little endian platform,
but you'd still want to include tests that are generic enough to
run on either little or big endian (but not tests that are specific
to other types of endianess), you could use::
$ avocado list byteorder.py --filter-by-tags endianess:big --filter-by-tags-include-empty-key
INSTRUMENTED byteorder.py:ByteOrder.test_be
INSTRUMENTED byteorder.py:Generic.test
Python :mod:`unittest` Compatibility Limitations And Caveats
============================================================
......
......@@ -465,7 +465,7 @@ class TagFilter(unittest.TestCase):
self.assertEqual(self.test_suite[6][1]['methodName'], 'test_no_tags')
def test_filter_fast_net(self):
filtered = loader.filter_test_tags(self.test_suite, ['fast,net'], False)
filtered = loader.filter_test_tags(self.test_suite, ['fast,net'], False, False)
self.assertEqual(len(filtered), 2)
self.assertEqual(filtered[0][0], 'FastTest')
self.assertEqual(filtered[0][1]['methodName'], 'test_fast')
......@@ -473,7 +473,7 @@ class TagFilter(unittest.TestCase):
self.assertEqual(filtered[1][1]['methodName'], 'test_fast_other')
def test_filter_fast_net_include_empty(self):
filtered = loader.filter_test_tags(self.test_suite, ['fast,net'], True)
filtered = loader.filter_test_tags(self.test_suite, ['fast,net'], True, False)
self.assertEqual(len(filtered), 3)
self.assertEqual(filtered[0][0], 'FastTest')
self.assertEqual(filtered[0][1]['methodName'], 'test_fast')
......@@ -483,24 +483,64 @@ class TagFilter(unittest.TestCase):
self.assertEqual(filtered[2][1]['methodName'], 'test_no_tags')
def test_filter_arch(self):
filtered = loader.filter_test_tags(self.test_suite, ['arch'], False)
filtered = loader.filter_test_tags(self.test_suite, ['arch'], False, False)
self.assertEqual(len(filtered), 1)
self.assertEqual(filtered[0][0], 'SafeX86Test')
self.assertEqual(filtered[0][1]['methodName'], 'test_safe_x86')
def test_filter_arch_include_empty(self):
filtered = loader.filter_test_tags(self.test_suite, ['arch'], True)
filtered = loader.filter_test_tags(self.test_suite, ['arch'], True, False)
self.assertEqual(len(filtered), 2)
self.assertEqual(filtered[0][0], 'SafeX86Test')
self.assertEqual(filtered[0][1]['methodName'], 'test_safe_x86')
self.assertEqual(filtered[1][0], 'NoTagsTest')
self.assertEqual(filtered[1][1]['methodName'], 'test_no_tags')
def test_filter_arch_x86_64(self):
filtered = loader.filter_test_tags(self.test_suite, ['arch:x86_64'], False, False)
self.assertEqual(len(filtered), 1)
self.assertEqual(filtered[0][0], 'SafeX86Test')
self.assertEqual(filtered[0][1]['methodName'], 'test_safe_x86')
def test_filter_arch_other(self):
filtered = loader.filter_test_tags(self.test_suite, ['arch:ppc64'], False, False)
self.assertEqual(len(filtered), 0)
def test_filter_arch_other_include_empty_key(self):
filtered = loader.filter_test_tags(self.test_suite, ['arch:ppc64'], False, True)
self.assertEqual(len(filtered), 5)
self.assertEqual(filtered[0][0], 'FastTest')
self.assertEqual(filtered[0][1]['methodName'], 'test_fast')
self.assertEqual(filtered[1][0], 'FastTest')
self.assertEqual(filtered[1][1]['methodName'], 'test_fast_other')
self.assertEqual(filtered[2][0], 'SlowTest')
self.assertEqual(filtered[2][1]['methodName'], 'test_slow')
self.assertEqual(filtered[3][0], 'SlowUnsafeTest')
self.assertEqual(filtered[3][1]['methodName'], 'test_slow_unsafe')
self.assertEqual(filtered[4][0], 'SafeTest')
self.assertEqual(filtered[4][1]['methodName'], 'test_safe')
def test_filter_arch_other_include_empty_flat_and_key(self):
filtered = loader.filter_test_tags(self.test_suite, ['arch:ppc64'], True, True)
self.assertEqual(len(filtered), 6)
self.assertEqual(filtered[0][0], 'FastTest')
self.assertEqual(filtered[0][1]['methodName'], 'test_fast')
self.assertEqual(filtered[1][0], 'FastTest')
self.assertEqual(filtered[1][1]['methodName'], 'test_fast_other')
self.assertEqual(filtered[2][0], 'SlowTest')
self.assertEqual(filtered[2][1]['methodName'], 'test_slow')
self.assertEqual(filtered[3][0], 'SlowUnsafeTest')
self.assertEqual(filtered[3][1]['methodName'], 'test_slow_unsafe')
self.assertEqual(filtered[4][0], 'SafeTest')
self.assertEqual(filtered[4][1]['methodName'], 'test_safe')
self.assertEqual(filtered[5][0], 'NoTagsTest')
self.assertEqual(filtered[5][1]['methodName'], 'test_no_tags')
def test_filter_fast_net__slow_disk_unsafe(self):
filtered = loader.filter_test_tags(self.test_suite,
['fast,net',
'slow,disk,unsafe'],
False)
False, False)
self.assertEqual(len(filtered), 3)
self.assertEqual(filtered[0][0], 'FastTest')
self.assertEqual(filtered[0][1]['methodName'], 'test_fast')
......@@ -513,7 +553,7 @@ class TagFilter(unittest.TestCase):
filtered = loader.filter_test_tags(self.test_suite,
['fast,net',
'slow,disk'],
False)
False, False)
self.assertEqual(len(filtered), 4)
self.assertEqual(filtered[0][0], 'FastTest')
self.assertEqual(filtered[0][1]['methodName'], 'test_fast')
......@@ -590,9 +630,9 @@ class TagFilter2(unittest.TestCase):
this_loader = loader.FileLoader(None, {})
test_suite = this_loader.discover(test_script.path,
loader.DiscoverMode.ALL)
self.assertEqual([], loader.filter_test_tags(test_suite, [], False))
self.assertEqual([], loader.filter_test_tags(test_suite, [], False, False))
self.assertEqual(test_suite,
loader.filter_test_tags(test_suite, [], True))
loader.filter_test_tags(test_suite, [], True, False))
class ParseFilterByTags(unittest.TestCase):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册