summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/core/context.py
diff options
context:
space:
mode:
authorAníbal Limón <anibal.limon@linux.intel.com>2016-11-09 10:38:37 -0600
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-01-23 12:05:18 +0000
commit13c8c08b95191829705b5a4c8f0d368c251f0174 (patch)
tree737412ed0d676dcf1982fc6b2cd0046bca760281 /meta/lib/oeqa/core/context.py
parentabb55ab304af91f68a4e09176ce9c6b995d903e0 (diff)
downloadpoky-13c8c08b95191829705b5a4c8f0d368c251f0174.tar.gz
oeqa/core: Add loader, context and decorator modules
loader: Implements OETestLoader handling OETestDecorator and filtering support when load tests. The OETestLoader is responsible to set custom methods, attrs of the OEQA frameowork. [YOCTO #10231] [YOCTO #10317] [YOCTO #10353] decorator: Add base class OETestDecorator to provide a common way to define decorators to be used over OETestCase's, every decorator has a method to be called when loading tests and before test execution starts. Special decorators could be implemented for filter tests on loading phase. context: Provides HIGH level API for loadTests and runTests of certain test component (i.e. runtime, sdk, selftest). [YOCTO #10230] (From OE-Core rev: 275ef03b77ef5f23b75cb01c55206d1ab0261342) Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com> Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa/core/context.py')
-rw-r--r--meta/lib/oeqa/core/context.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py
new file mode 100644
index 0000000000..cbab2f8f5f
--- /dev/null
+++ b/meta/lib/oeqa/core/context.py
@@ -0,0 +1,148 @@
1# Copyright (C) 2016 Intel Corporation
2# Released under the MIT license (see COPYING.MIT)
3
4import os
5import sys
6import json
7import time
8import logging
9import collections
10import re
11
12from oeqa.core.loader import OETestLoader
13from oeqa.core.runner import OETestRunner, OEStreamLogger, xmlEnabled
14
15class OETestContext(object):
16 loaderClass = OETestLoader
17 runnerClass = OETestRunner
18 streamLoggerClass = OEStreamLogger
19
20 files_dir = os.path.abspath(os.path.join(os.path.dirname(
21 os.path.abspath(__file__)), "../files"))
22
23 def __init__(self, td=None, logger=None):
24 if not type(td) is dict:
25 raise TypeError("td isn't dictionary type")
26
27 self.td = td
28 self.logger = logger
29 self._registry = {}
30 self._registry['cases'] = collections.OrderedDict()
31 self._results = {}
32
33 def _read_modules_from_manifest(self, manifest):
34 if not os.path.exists(manifest):
35 raise
36
37 modules = []
38 for line in open(manifest).readlines():
39 line = line.strip()
40 if line and not line.startswith("#"):
41 modules.append(line)
42
43 return modules
44
45 def loadTests(self, module_paths, modules=[], tests=[],
46 modules_manifest="", modules_required=[], filters={}):
47 if modules_manifest:
48 modules = self._read_modules_from_manifest(modules_manifest)
49
50 self.loader = self.loaderClass(self, module_paths, modules, tests,
51 modules_required, filters)
52 self.suites = self.loader.discover()
53
54 def runTests(self):
55 streamLogger = self.streamLoggerClass(self.logger)
56 self.runner = self.runnerClass(self, stream=streamLogger, verbosity=2)
57
58 self._run_start_time = time.time()
59 result = self.runner.run(self.suites)
60 self._run_end_time = time.time()
61
62 return result
63
64 def logSummary(self, result, component, context_msg=''):
65 self.logger.info("SUMMARY:")
66 self.logger.info("%s (%s) - Ran %d test%s in %.3fs" % (component,
67 context_msg, result.testsRun, result.testsRun != 1 and "s" or "",
68 (self._run_end_time - self._run_start_time)))
69
70 if result.wasSuccessful():
71 msg = "%s - OK - All required tests passed" % component
72 else:
73 msg = "%s - FAIL - Required tests failed" % component
74 skipped = len(self._results['skipped'])
75 if skipped:
76 msg += " (skipped=%d)" % skipped
77 self.logger.info(msg)
78
79 def _getDetailsNotPassed(self, case, type, desc):
80 found = False
81
82 for (scase, msg) in self._results[type]:
83 # XXX: When XML reporting is enabled scase is
84 # xmlrunner.result._TestInfo instance instead of
85 # string.
86 if xmlEnabled:
87 if case.id() == scase.test_id:
88 found = True
89 break
90 scase_str = scase.test_id
91 else:
92 if case == scase:
93 found = True
94 break
95 scase_str = str(scase)
96
97 # When fails at module or class level the class name is passed as string
98 # so figure out to see if match
99 m = re.search("^setUpModule \((?P<module_name>.*)\)$", scase_str)
100 if m:
101 if case.__class__.__module__ == m.group('module_name'):
102 found = True
103 break
104
105 m = re.search("^setUpClass \((?P<class_name>.*)\)$", scase_str)
106 if m:
107 class_name = "%s.%s" % (case.__class__.__module__,
108 case.__class__.__name__)
109
110 if class_name == m.group('class_name'):
111 found = True
112 break
113
114 if found:
115 return (found, msg)
116
117 return (found, None)
118
119 def logDetails(self):
120 self.logger.info("RESULTS:")
121 for case_name in self._registry['cases']:
122 case = self._registry['cases'][case_name]
123
124 result_types = ['failures', 'errors', 'skipped', 'expectedFailures']
125 result_desc = ['FAILED', 'ERROR', 'SKIPPED', 'EXPECTEDFAIL']
126
127 fail = False
128 desc = None
129 for idx, name in enumerate(result_types):
130 (fail, msg) = self._getDetailsNotPassed(case, result_types[idx],
131 result_desc[idx])
132 if fail:
133 desc = result_desc[idx]
134 break
135
136 oeid = -1
137 for d in case.decorators:
138 if hasattr(d, 'oeid'):
139 oeid = d.oeid
140
141 if fail:
142 self.logger.info("RESULTS - %s - Testcase %s: %s" % (case.id(),
143 oeid, desc))
144 if msg:
145 self.logger.info(msg)
146 else:
147 self.logger.info("RESULTS - %s - Testcase %s: %s" % (case.id(),
148 oeid, 'PASSED'))