|
| 1 | +from functools import partial |
| 2 | +import unittest |
| 3 | +import nose |
| 4 | +import nose.config |
| 5 | +import nose.core |
| 6 | +import os |
| 7 | +import sys |
| 8 | +import logging |
| 9 | +from cloudstackTestCase import cloudstackTestCase |
| 10 | +from nose.suite import ContextSuite, ContextSuiteFactory |
| 11 | + |
| 12 | +class CloudStackTestSelector(nose.selector.Selector): |
| 13 | + """ |
| 14 | + custom test selector for cloudstackTestCase |
| 15 | + """ |
| 16 | + |
| 17 | + def wantClass(self, cls): |
| 18 | + if issubclass(cls, cloudstackTestCase): |
| 19 | + return nose.selector.Selector.wantClass(self, cls) |
| 20 | + |
| 21 | +def testCaseLogger(message, logger=None): |
| 22 | + if logger is not None: |
| 23 | + logger.debug(message) |
| 24 | + |
| 25 | +class NoseTestExecuteEngine(object): |
| 26 | + def __init__(self, testclient=None, workingdir=None, clientLog=None, resultLog=None): |
| 27 | + self.testclient = testclient |
| 28 | + self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") |
| 29 | + self.suite = [] |
| 30 | + realPath = os.path.abspath(workingdir) |
| 31 | + |
| 32 | + if clientLog is not None: |
| 33 | + self.logfile = clientLog |
| 34 | + self.logger = logging.getLogger("NoseTestExecuteEngine") |
| 35 | + fh = logging.FileHandler(self.logfile) |
| 36 | + fh.setFormatter(self.logformat) |
| 37 | + self.logger.addHandler(fh) |
| 38 | + self.logger.setLevel(logging.DEBUG) |
| 39 | + if resultLog is not None: |
| 40 | + ch = logging.StreamHandler() |
| 41 | + ch.setLevel(logging.ERROR) |
| 42 | + ch.setFormatter(self.logformat) |
| 43 | + self.logger.addHandler(ch) |
| 44 | + fp = open(resultLog, "w") |
| 45 | + self.testResultLogFile = fp |
| 46 | + else: |
| 47 | + self.testResultLogFile = sys.stdout |
| 48 | + |
| 49 | + if workingdir is not None and os.path.exists(realPath + '/' + '__init__.py'): |
| 50 | + self.loader = nose.loader.TestLoader() |
| 51 | + [self.suite.append(test) for test in self.loader.discover(workingdir, "test*.py")] |
| 52 | + for test in self.suite: |
| 53 | + self.injectTestCase(test) |
| 54 | + print self.suite[0].countTestCases() |
| 55 | + else: |
| 56 | + print "Single module test runs unsupported using Nose" |
| 57 | + raise |
| 58 | + |
| 59 | + self.runner = nose.core.TextTestRunner(stream=self.testResultLogFile, descriptions=1, verbosity=2, config=None) |
| 60 | + |
| 61 | + def runTests(self): |
| 62 | + #testProgram = nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner = self.runner, testLoader = self.loader) |
| 63 | + testProgram = nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner = self.runner, suite = self.suite) |
| 64 | + testProgram.runTests() |
| 65 | + |
| 66 | + def injectTestCase(self, testSuites): |
| 67 | + for test in testSuites: |
| 68 | + if isinstance(test, unittest.BaseTestSuite): |
| 69 | + self.injectTestCase(test) |
| 70 | + else: |
| 71 | + #logger bears the name of the test class |
| 72 | + testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) |
| 73 | + fh = logging.FileHandler(self.logfile) |
| 74 | + fh.setFormatter(self.logformat) |
| 75 | + testcaselogger.addHandler(fh) |
| 76 | + testcaselogger.setLevel(logging.DEBUG) |
| 77 | + |
| 78 | + #inject testclient and logger into each unittest |
| 79 | + setattr(test, "testClient", self.testclient) |
| 80 | + setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) |
| 81 | + setattr(test.__class__, "clstestclient", self.testclient) |
| 82 | + if hasattr(test, "UserName"): |
| 83 | + self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) |
0 commit comments