diff options
-rw-r--r-- | meta/classes/testimage.bbclass | 6 | ||||
-rw-r--r-- | meta/lib/oeqa/oetest.py | 56 | ||||
-rw-r--r-- | meta/lib/oeqa/utils/decorators.py | 1 |
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 | ||
34 | def runTests(tc, type="runtime"): | 84 | def 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 | ||
90 | class testcase(object): | 91 | class testcase(object): |