diff options
Diffstat (limited to 'meta/lib')
| -rw-r--r-- | meta/lib/oeqa/oetest.py | 56 | ||||
| -rw-r--r-- | meta/lib/oeqa/utils/decorators.py | 1 |
2 files changed, 54 insertions, 3 deletions
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): |
