summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/testimage.bbclass6
-rw-r--r--meta/lib/oeqa/oetest.py56
-rw-r--r--meta/lib/oeqa/utils/decorators.py1
3 files changed, 59 insertions, 4 deletions
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 683173854d..dc163c7313 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -16,7 +16,11 @@
16# The test names are the module names in meta/lib/oeqa/runtime. 16# The test names are the module names in meta/lib/oeqa/runtime.
17# Each name in TEST_SUITES represents a required test for the image. (no skipping allowed) 17# Each name in TEST_SUITES represents a required test for the image. (no skipping allowed)
18# Appending "auto" means that it will try to run all tests that are suitable for the image (each test decides that on it's own). 18# Appending "auto" means that it will try to run all tests that are suitable for the image (each test decides that on it's own).
19# Note that order in TEST_SUITES is important (it's the order tests run) and it influences tests dependencies. 19# Note that order in TEST_SUITES is relevant: tests are run in an order such that
20# tests mentioned in @skipUnlessPassed run before the tests that depend on them,
21# but without such dependencies, tests run in the order in which they are listed
22# in TEST_SUITES.
23#
20# A layer can add its own tests in lib/oeqa/runtime, provided it extends BBPATH as normal in its layer.conf. 24# A layer can add its own tests in lib/oeqa/runtime, provided it extends BBPATH as normal in its layer.conf.
21 25
22# TEST_LOG_DIR contains a command ssh log and may contain infromation about what command is running, output and return codes and for qemu a boot log till login. 26# TEST_LOG_DIR contains a command ssh log and may contain infromation about what command is running, output and return codes and for qemu a boot log till login.
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index a3c5c1d358..da9556a6da 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -27,9 +27,59 @@ def loadTests(tc, type="runtime"):
27 setattr(oeTest, "tc", tc) 27 setattr(oeTest, "tc", tc)
28 testloader = unittest.TestLoader() 28 testloader = unittest.TestLoader()
29 testloader.sortTestMethodsUsing = None 29 testloader.sortTestMethodsUsing = None
30 suite = testloader.loadTestsFromNames(tc.testslist) 30 suites = [testloader.loadTestsFromName(name) for name in tc.testslist]
31 31
32 return suite 32 def getTests(test):
33 '''Return all individual tests executed when running the suite.'''
34 # Unfortunately unittest does not have an API for this, so we have
35 # to rely on implementation details. This only needs to work
36 # for TestSuite containing TestCase.
37 method = getattr(test, '_testMethodName', None)
38 if method:
39 # leaf case: a TestCase
40 yield test
41 else:
42 # Look into TestSuite.
43 tests = getattr(test, '_tests', [])
44 for t1 in tests:
45 for t2 in getTests(t1):
46 yield t2
47
48 # Determine dependencies between suites by looking for @skipUnlessPassed
49 # method annotations. Suite A depends on suite B if any method in A
50 # depends on a method on B.
51 for suite in suites:
52 suite.dependencies = []
53 suite.depth = 0
54 for test in getTests(suite):
55 methodname = getattr(test, '_testMethodName', None)
56 if methodname:
57 method = getattr(test, methodname)
58 depends_on = getattr(method, '_depends_on', None)
59 if depends_on:
60 for dep_suite in suites:
61 if depends_on in [getattr(t, '_testMethodName', None) for t in getTests(dep_suite)]:
62 if dep_suite not in suite.dependencies and \
63 dep_suite is not suite:
64 suite.dependencies.append(dep_suite)
65 break
66 else:
67 bb.warn("Test %s was declared as @skipUnlessPassed('%s') but that test is either not defined or not active. Will run the test anyway." %
68 (test, depends_on))
69 # Use brute-force topological sort to determine ordering. Sort by
70 # depth (higher depth = must run later), with original ordering to
71 # break ties.
72 def set_suite_depth(suite):
73 for dep in suite.dependencies:
74 new_depth = set_suite_depth(dep) + 1
75 if new_depth > suite.depth:
76 suite.depth = new_depth
77 return suite.depth
78 for index, suite in enumerate(suites):
79 set_suite_depth(suite)
80 suite.index = index
81 suites.sort(cmp=lambda a,b: cmp((a.depth, a.index), (b.depth, b.index)))
82 return testloader.suiteClass(suites)
33 83
34def runTests(tc, type="runtime"): 84def runTests(tc, type="runtime"):
35 85
diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py
index ff5f278bc1..1e5a890fdd 100644
--- a/meta/lib/oeqa/utils/decorators.py
+++ b/meta/lib/oeqa/utils/decorators.py
@@ -85,6 +85,7 @@ class skipUnlessPassed(object):
85 raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase) 85 raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
86 return f(*args) 86 return f(*args)
87 wrapped_f.__name__ = f.__name__ 87 wrapped_f.__name__ = f.__name__
88 wrapped_f._depends_on = self.testcase
88 return wrapped_f 89 return wrapped_f
89 90
90class testcase(object): 91class testcase(object):