summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/core
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/core')
-rw-r--r--meta/lib/oeqa/core/context.py4
-rw-r--r--meta/lib/oeqa/core/decorator/__init__.py20
-rw-r--r--meta/lib/oeqa/core/decorator/oetag.py27
-rw-r--r--meta/lib/oeqa/core/loader.py61
-rw-r--r--meta/lib/oeqa/core/tests/cases/data.py2
-rw-r--r--meta/lib/oeqa/core/tests/cases/oetag.py21
-rw-r--r--meta/lib/oeqa/core/tests/common.py4
-rwxr-xr-xmeta/lib/oeqa/core/tests/test_decorators.py77
-rwxr-xr-xmeta/lib/oeqa/core/tests/test_loader.py25
9 files changed, 103 insertions, 138 deletions
diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py
index 68819cc338..14fc6a54f4 100644
--- a/meta/lib/oeqa/core/context.py
+++ b/meta/lib/oeqa/core/context.py
@@ -64,12 +64,12 @@ class OETestContext(object):
64 setattr(tclass, 'setUpHooker', skipfuncgen('Skip by the command line argument "%s"' % skip)) 64 setattr(tclass, 'setUpHooker', skipfuncgen('Skip by the command line argument "%s"' % skip))
65 65
66 def loadTests(self, module_paths, modules=[], tests=[], 66 def loadTests(self, module_paths, modules=[], tests=[],
67 modules_manifest="", modules_required=[], filters={}): 67 modules_manifest="", modules_required=[], **kwargs):
68 if modules_manifest: 68 if modules_manifest:
69 modules = self._read_modules_from_manifest(modules_manifest) 69 modules = self._read_modules_from_manifest(modules_manifest)
70 70
71 self.loader = self.loaderClass(self, module_paths, modules, tests, 71 self.loader = self.loaderClass(self, module_paths, modules, tests,
72 modules_required, filters) 72 modules_required, **kwargs)
73 self.suites = self.loader.discover() 73 self.suites = self.loader.discover()
74 74
75 def runTests(self, processes=None, skips=[]): 75 def runTests(self, processes=None, skips=[]):
diff --git a/meta/lib/oeqa/core/decorator/__init__.py b/meta/lib/oeqa/core/decorator/__init__.py
index 923b218266..1a5ac40134 100644
--- a/meta/lib/oeqa/core/decorator/__init__.py
+++ b/meta/lib/oeqa/core/decorator/__init__.py
@@ -6,6 +6,7 @@
6 6
7from functools import wraps 7from functools import wraps
8from abc import abstractmethod, ABCMeta 8from abc import abstractmethod, ABCMeta
9from oeqa.core.utils.misc import strToList
9 10
10decoratorClasses = set() 11decoratorClasses = set()
11 12
@@ -63,12 +64,15 @@ class OETestDiscover(OETestDecorator):
63 def discover(registry): 64 def discover(registry):
64 return registry['cases'] 65 return registry['cases']
65 66
66class OETestFilter(OETestDecorator): 67def OETestTag(*tags):
68 expandedtags = []
69 for tag in tags:
70 expandedtags += strToList(tag)
71 def decorator(item):
72 if hasattr(item, "__oeqa_testtags"):
73 item.__oeqa_testtags += expandedtags
74 else:
75 item.__oeqa_testtags = expandedtags
76 return item
77 return decorator
67 78
68 # OETestLoader call it while loading the tests
69 # in loadTestsFromTestCase method, it needs to
70 # return a bool, True if needs to be filtered.
71 # This method must consume the filter used.
72 @abstractmethod
73 def filtrate(self, filters):
74 return False
diff --git a/meta/lib/oeqa/core/decorator/oetag.py b/meta/lib/oeqa/core/decorator/oetag.py
deleted file mode 100644
index 8c31138dac..0000000000
--- a/meta/lib/oeqa/core/decorator/oetag.py
+++ /dev/null
@@ -1,27 +0,0 @@
1#
2# Copyright (C) 2016 Intel Corporation
3#
4# SPDX-License-Identifier: MIT
5#
6
7from . import OETestFilter, registerDecorator
8from oeqa.core.utils.misc import strToList
9
10def _tagFilter(tags, filters):
11 return False if set(tags) & set(filters) else True
12
13@registerDecorator
14class OETestTag(OETestFilter):
15 attrs = ('oetag',)
16
17 def bind(self, registry, case):
18 super(OETestTag, self).bind(registry, case)
19 self.oetag = strToList(self.oetag, 'oetag')
20
21 def filtrate(self, filters):
22 if filters.get('oetag'):
23 filterx = strToList(filters['oetag'], 'oetag')
24 del filters['oetag']
25 if _tagFilter(self.oetag, filterx):
26 return True
27 return False
diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py
index 7fea0585c7..0d7970d49e 100644
--- a/meta/lib/oeqa/core/loader.py
+++ b/meta/lib/oeqa/core/loader.py
@@ -16,7 +16,7 @@ from oeqa.core.utils.test import getSuiteModules, getCaseID
16from oeqa.core.exception import OEQATestNotFound 16from oeqa.core.exception import OEQATestNotFound
17from oeqa.core.case import OETestCase 17from oeqa.core.case import OETestCase
18from oeqa.core.decorator import decoratorClasses, OETestDecorator, \ 18from oeqa.core.decorator import decoratorClasses, OETestDecorator, \
19 OETestFilter, OETestDiscover 19 OETestDiscover
20 20
21# When loading tests, the unittest framework stores any exceptions and 21# When loading tests, the unittest framework stores any exceptions and
22# displays them only when the run method is called. 22# displays them only when the run method is called.
@@ -68,7 +68,7 @@ class OETestLoader(unittest.TestLoader):
68 '_top_level_dir'] 68 '_top_level_dir']
69 69
70 def __init__(self, tc, module_paths, modules, tests, modules_required, 70 def __init__(self, tc, module_paths, modules, tests, modules_required,
71 filters, *args, **kwargs): 71 *args, **kwargs):
72 self.tc = tc 72 self.tc = tc
73 73
74 self.modules = _built_modules_dict(modules) 74 self.modules = _built_modules_dict(modules)
@@ -76,13 +76,7 @@ class OETestLoader(unittest.TestLoader):
76 self.tests = tests 76 self.tests = tests
77 self.modules_required = modules_required 77 self.modules_required = modules_required
78 78
79 self.filters = filters 79 self.tags_filter = kwargs.get("tags_filter", None)
80 self.decorator_filters = [d for d in decoratorClasses if \
81 issubclass(d, OETestFilter)]
82 self._validateFilters(self.filters, self.decorator_filters)
83 self.used_filters = [d for d in self.decorator_filters
84 for f in self.filters
85 if f in d.attrs]
86 80
87 if isinstance(module_paths, str): 81 if isinstance(module_paths, str):
88 module_paths = [module_paths] 82 module_paths = [module_paths]
@@ -104,28 +98,6 @@ class OETestLoader(unittest.TestLoader):
104 setattr(testCaseClass, 'td', self.tc.td) 98 setattr(testCaseClass, 'td', self.tc.td)
105 setattr(testCaseClass, 'logger', self.tc.logger) 99 setattr(testCaseClass, 'logger', self.tc.logger)
106 100
107 def _validateFilters(self, filters, decorator_filters):
108 # Validate if filter isn't empty
109 for key,value in filters.items():
110 if not value:
111 raise TypeError("Filter %s specified is empty" % key)
112
113 # Validate unique attributes
114 attr_filters = [attr for clss in decorator_filters \
115 for attr in clss.attrs]
116 dup_attr = [attr for attr in attr_filters
117 if attr_filters.count(attr) > 1]
118 if dup_attr:
119 raise TypeError('Detected duplicated attribute(s) %s in filter'
120 ' decorators' % ' ,'.join(dup_attr))
121
122 # Validate if filter is supported
123 for f in filters:
124 if f not in attr_filters:
125 classes = ', '.join([d.__name__ for d in decorator_filters])
126 raise TypeError('Found "%s" filter but not declared in any of '
127 '%s decorators' % (f, classes))
128
129 def _registerTestCase(self, case): 101 def _registerTestCase(self, case):
130 case_id = case.id() 102 case_id = case.id()
131 self.tc._registry['cases'][case_id] = case 103 self.tc._registry['cases'][case_id] = case
@@ -188,19 +160,20 @@ class OETestLoader(unittest.TestLoader):
188 return True 160 return True
189 161
190 # Decorator filters 162 # Decorator filters
191 if self.filters and isinstance(case, OETestCase): 163 if self.tags_filter is not None and callable(self.tags_filter):
192 filters = self.filters.copy() 164 alltags = set()
193 case_decorators = [cd for cd in case.decorators 165 # pull tags from the case class
194 if cd.__class__ in self.used_filters] 166 if hasattr(case, "__oeqa_testtags"):
195 167 for t in getattr(case, "__oeqa_testtags"):
196 # Iterate over case decorators to check if needs to be filtered. 168 alltags.add(t)
197 for cd in case_decorators: 169 # pull tags from the method itself
198 if cd.filtrate(filters): 170 if hasattr(case, test_name):
199 return True 171 method = getattr(case, test_name)
200 172 if hasattr(method, "__oeqa_testtags"):
201 # Case is missing one or more decorators for all the filters 173 for t in getattr(method, "__oeqa_testtags"):
202 # being used, so filter test case. 174 alltags.add(t)
203 if filters: 175
176 if self.tags_filter(alltags):
204 return True 177 return True
205 178
206 return False 179 return False
diff --git a/meta/lib/oeqa/core/tests/cases/data.py b/meta/lib/oeqa/core/tests/cases/data.py
index 0d8de87ae7..61f88547f7 100644
--- a/meta/lib/oeqa/core/tests/cases/data.py
+++ b/meta/lib/oeqa/core/tests/cases/data.py
@@ -5,7 +5,7 @@
5# 5#
6 6
7from oeqa.core.case import OETestCase 7from oeqa.core.case import OETestCase
8from oeqa.core.decorator.oetag import OETestTag 8from oeqa.core.decorator import OETestTag
9from oeqa.core.decorator.data import OETestDataDepends 9from oeqa.core.decorator.data import OETestDataDepends
10 10
11class DataTest(OETestCase): 11class DataTest(OETestCase):
diff --git a/meta/lib/oeqa/core/tests/cases/oetag.py b/meta/lib/oeqa/core/tests/cases/oetag.py
index 4e1d080985..52f97dfda6 100644
--- a/meta/lib/oeqa/core/tests/cases/oetag.py
+++ b/meta/lib/oeqa/core/tests/cases/oetag.py
@@ -5,10 +5,9 @@
5# 5#
6 6
7from oeqa.core.case import OETestCase 7from oeqa.core.case import OETestCase
8from oeqa.core.decorator.oetag import OETestTag 8from oeqa.core.decorator import OETestTag
9 9
10class TagTest(OETestCase): 10class TagTest(OETestCase):
11
12 @OETestTag('goodTag') 11 @OETestTag('goodTag')
13 def testTagGood(self): 12 def testTagGood(self):
14 self.assertTrue(True, msg='How is this possible?') 13 self.assertTrue(True, msg='How is this possible?')
@@ -17,5 +16,23 @@ class TagTest(OETestCase):
17 def testTagOther(self): 16 def testTagOther(self):
18 self.assertTrue(True, msg='How is this possible?') 17 self.assertTrue(True, msg='How is this possible?')
19 18
19 @OETestTag('otherTag', 'multiTag')
20 def testTagOtherMulti(self):
21 self.assertTrue(True, msg='How is this possible?')
22
20 def testTagNone(self): 23 def testTagNone(self):
21 self.assertTrue(True, msg='How is this possible?') 24 self.assertTrue(True, msg='How is this possible?')
25
26@OETestTag('classTag')
27class TagClassTest(OETestCase):
28 @OETestTag('otherTag')
29 def testTagOther(self):
30 self.assertTrue(True, msg='How is this possible?')
31
32 @OETestTag('otherTag', 'multiTag')
33 def testTagOtherMulti(self):
34 self.assertTrue(True, msg='How is this possible?')
35
36 def testTagNone(self):
37 self.assertTrue(True, msg='How is this possible?')
38
diff --git a/meta/lib/oeqa/core/tests/common.py b/meta/lib/oeqa/core/tests/common.py
index 39efd504c0..88cc758ad3 100644
--- a/meta/lib/oeqa/core/tests/common.py
+++ b/meta/lib/oeqa/core/tests/common.py
@@ -30,9 +30,9 @@ class TestBase(unittest.TestCase):
30 directory = os.path.dirname(os.path.abspath(__file__)) 30 directory = os.path.dirname(os.path.abspath(__file__))
31 self.cases_path = os.path.join(directory, 'cases') 31 self.cases_path = os.path.join(directory, 'cases')
32 32
33 def _testLoader(self, d={}, modules=[], tests=[], filters={}): 33 def _testLoader(self, d={}, modules=[], tests=[], **kwargs):
34 from oeqa.core.context import OETestContext 34 from oeqa.core.context import OETestContext
35 tc = OETestContext(d, self.logger) 35 tc = OETestContext(d, self.logger)
36 tc.loadTests(self.cases_path, modules=modules, tests=tests, 36 tc.loadTests(self.cases_path, modules=modules, tests=tests,
37 filters=filters) 37 **kwargs)
38 return tc 38 return tc
diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py
index 499cd66ff3..b798bf7d33 100755
--- a/meta/lib/oeqa/core/tests/test_decorators.py
+++ b/meta/lib/oeqa/core/tests/test_decorators.py
@@ -14,35 +14,58 @@ setup_sys_path()
14from oeqa.core.exception import OEQADependency 14from oeqa.core.exception import OEQADependency
15from oeqa.core.utils.test import getCaseMethod, getSuiteCasesNames, getSuiteCasesIDs 15from oeqa.core.utils.test import getCaseMethod, getSuiteCasesNames, getSuiteCasesIDs
16 16
17class TestFilterDecorator(TestBase): 17class TestTagDecorator(TestBase):
18 18 def _runTest(self, modules, filterfn, expect):
19 def _runFilterTest(self, modules, filters, expect, msg): 19 tc = self._testLoader(modules = modules, tags_filter = filterfn)
20 tc = self._testLoader(modules=modules, filters=filters) 20 test_loaded = set(getSuiteCasesIDs(tc.suites))
21 test_loaded = set(getSuiteCasesNames(tc.suites)) 21 self.assertEqual(expect, test_loaded)
22 self.assertEqual(expect, test_loaded, msg=msg)
23 22
24 def test_oetag(self): 23 def test_oetag(self):
25 # Get all cases without filtering. 24 # get all cases without any filtering
26 filter_all = {} 25 self._runTest(['oetag'], None, {
27 test_all = {'testTagGood', 'testTagOther', 'testTagNone'} 26 'oetag.TagTest.testTagGood',
28 msg_all = 'Failed to get all oetag cases without filtering.' 27 'oetag.TagTest.testTagOther',
29 28 'oetag.TagTest.testTagOtherMulti',
30 # Get cases with 'goodTag'. 29 'oetag.TagTest.testTagNone',
31 filter_good = {'oetag':'goodTag'} 30 'oetag.TagClassTest.testTagOther',
32 test_good = {'testTagGood'} 31 'oetag.TagClassTest.testTagOtherMulti',
33 msg_good = 'Failed to get just one test filtering with "goodTag" oetag.' 32 'oetag.TagClassTest.testTagNone',
34 33 })
35 # Get cases with an invalid tag. 34
36 filter_invalid = {'oetag':'invalidTag'} 35 # exclude any case with tags
37 test_invalid = set() 36 self._runTest(['oetag'], lambda tags: tags, {
38 msg_invalid = 'Failed to filter all test using an invalid oetag.' 37 'oetag.TagTest.testTagNone',
39 38 })
40 tests = ((filter_all, test_all, msg_all), 39
41 (filter_good, test_good, msg_good), 40 # exclude any case with otherTag
42 (filter_invalid, test_invalid, msg_invalid)) 41 self._runTest(['oetag'], lambda tags: "otherTag" in tags, {
43 42 'oetag.TagTest.testTagGood',
44 for test in tests: 43 'oetag.TagTest.testTagNone',
45 self._runFilterTest(['oetag'], test[0], test[1], test[2]) 44 'oetag.TagClassTest.testTagNone',
45 })
46
47 # exclude any case with classTag
48 self._runTest(['oetag'], lambda tags: "classTag" in tags, {
49 'oetag.TagTest.testTagGood',
50 'oetag.TagTest.testTagOther',
51 'oetag.TagTest.testTagOtherMulti',
52 'oetag.TagTest.testTagNone',
53 })
54
55 # include any case with classTag
56 self._runTest(['oetag'], lambda tags: "classTag" not in tags, {
57 'oetag.TagClassTest.testTagOther',
58 'oetag.TagClassTest.testTagOtherMulti',
59 'oetag.TagClassTest.testTagNone',
60 })
61
62 # include any case with classTag or no tags
63 self._runTest(['oetag'], lambda tags: tags and "classTag" not in tags, {
64 'oetag.TagTest.testTagNone',
65 'oetag.TagClassTest.testTagOther',
66 'oetag.TagClassTest.testTagOtherMulti',
67 'oetag.TagClassTest.testTagNone',
68 })
46 69
47class TestDependsDecorator(TestBase): 70class TestDependsDecorator(TestBase):
48 modules = ['depends'] 71 modules = ['depends']
diff --git a/meta/lib/oeqa/core/tests/test_loader.py b/meta/lib/oeqa/core/tests/test_loader.py
index e73c91b141..cb38ac845e 100755
--- a/meta/lib/oeqa/core/tests/test_loader.py
+++ b/meta/lib/oeqa/core/tests/test_loader.py
@@ -15,31 +15,6 @@ from oeqa.core.exception import OEQADependency
15from oeqa.core.utils.test import getSuiteModules, getSuiteCasesIDs 15from oeqa.core.utils.test import getSuiteModules, getSuiteCasesIDs
16 16
17class TestLoader(TestBase): 17class TestLoader(TestBase):
18
19 def test_fail_empty_filter(self):
20 filters = {'oetag' : ''}
21 expect = 'Filter oetag specified is empty'
22 msg = 'Expected TypeError exception for having invalid filter'
23 try:
24 # Must throw TypeError because empty filter
25 tc = self._testLoader(filters=filters)
26 self.fail(msg)
27 except TypeError as e:
28 result = True if expect in str(e) else False
29 self.assertTrue(result, msg=msg)
30
31 def test_fail_invalid_filter(self):
32 filters = {'invalid' : 'good'}
33 expect = 'filter but not declared in any of'
34 msg = 'Expected TypeError exception for having invalid filter'
35 try:
36 # Must throw TypeError because invalid filter
37 tc = self._testLoader(filters=filters)
38 self.fail(msg)
39 except TypeError as e:
40 result = True if expect in str(e) else False
41 self.assertTrue(result, msg=msg)
42
43 @unittest.skip("invalid directory is missing oetag.py") 18 @unittest.skip("invalid directory is missing oetag.py")
44 def test_fail_duplicated_module(self): 19 def test_fail_duplicated_module(self):
45 cases_path = self.cases_path 20 cases_path = self.cases_path