You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ts...@apache.org on 2012/07/30 12:07:19 UTC

[6/16] git commit: Plugin-izing the testcase runner

Plugin-izing the testcase runner

* setup.py is the installer for marvin-nose plugin
* marvin-nose drive all tests using nose with other plugins like xunit, coverage, multiprocess execution etc
* -n option deprecated. All tests driven by nosetests --with-marvin


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/13857700
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/13857700
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/13857700

Branch: refs/heads/master
Commit: 13857700d38ed8a221f2353e927c8cd2d2df56c9
Parents: ed113ca
Author: Prasanna Santhanam <Pr...@citrix.com>
Authored: Mon Jul 23 19:23:04 2012 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Mon Jul 30 15:32:34 2012 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/deployAndRun.py |   22 +++-------
 tools/marvin/marvin/marvinPlugin.py |   73 ++++++++++++++++++++++++-----
 tools/marvin/marvin/setup.py        |   29 ++++++++++++
 3 files changed, 95 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/13857700/tools/marvin/marvin/deployAndRun.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py
index 31faa09..1c82d9f 100644
--- a/tools/marvin/marvin/deployAndRun.py
+++ b/tools/marvin/marvin/deployAndRun.py
@@ -17,7 +17,6 @@
 
 import deployDataCenter
 import TestCaseExecuteEngine
-import NoseTestExecuteEngine
 from optparse import OptionParser
 import os
 
@@ -31,7 +30,6 @@ if __name__ == "__main__":
     parser.add_option("-t", "--client", dest="testcaselog", help="test case log file")
     parser.add_option("-l", "--load", dest="load", action="store_true", help="only load config, do not deploy, it will only run testcase")
     parser.add_option("-f", "--file", dest="module", help="run tests in the given file")
-    parser.add_option("-n", "--nose", dest="nose", action="store_true", help="run tests using nose")
     parser.add_option("-x", "--xml", dest="xmlrunner", help="use the xml runner to generate xml reports and path to store xml files")
     (options, args) = parser.parse_args()
     
@@ -59,18 +57,10 @@ if __name__ == "__main__":
             parser.print_usage()
             exit(1)
         else:
-            if options.nose:
-                engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir)
-                engine.runTestsFromFile(options.module)
-            else:
-                engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir)
-                engine.loadTestsFromFile(options.module)
-                engine.run()
+            engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir)
+            engine.loadTestsFromFile(options.module)
+            engine.run()
     else:
-        if options.nose:
-            engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, clientLog=testCaseLogFile, resultLog=testResultLogFile, workingdir=options.testCaseFolder, format=format, xmlDir=xmlDir)
-            engine.runTests()
-        else:
-           engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir)
-           engine.loadTestsFromDir(options.testCaseFolder)
-           engine.run()
+       engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir)
+       engine.loadTestsFromDir(options.testCaseFolder)
+       engine.run()

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/13857700/tools/marvin/marvin/marvinPlugin.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py
index 9d52362..b99c14f 100644
--- a/tools/marvin/marvin/marvinPlugin.py
+++ b/tools/marvin/marvin/marvinPlugin.py
@@ -1,7 +1,10 @@
-from cloudstackTestCase import cloudstackTestCase
+import marvin
+import logging
+import nose.core
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin import deployDataCenter
 from nose.plugins.base import Plugin
 from functools import partial
-import logging
 
 def testCaseLogger(message, logger=None):
     if logger is not None:
@@ -9,21 +12,69 @@ def testCaseLogger(message, logger=None):
        
 class MarvinPlugin(Plugin):
     """
-    Custom test loader for the cloudstackTestCase to be loaded into nose
+    Custom plugin for the cloudstackTestCases to be run using nose
     """
     
     name = "marvin"
-    def configure(self, options, conf):
+    def configure(self, options, config):
         self.enabled = 1
         self.enableOpt = "--with-marvin"
-        return Plugin.configure(self, options, conf)
+        self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
+
+        if options.debug_log:
+            self.logger = logging.getLogger("NoseTestExecuteEngine")
+            self.debug_stream = logging.FileHandler(options.debug_log) 
+            self.debug_stream.setFormatter(self.logformat)
+            self.logger.addHandler(self.debug_stream)
+            self.logger.setLevel(logging.DEBUG)
+            
+        if options.result_log:
+            ch = logging.StreamHandler()
+            ch.setLevel(logging.ERROR)
+            ch.setFormatter(self.logformat)
+            self.logger.addHandler(ch)
+            self.result_stream = open(options.result_log, "w")
+        else:
+            self.result_stream = sys.stderr   
+    
+        deploy = deployDataCenter.deployDataCenters(options.config) 
+        deploy.loadCfg() if options.load else deploy.deploy()
+        self.setClient(deploy.testClient)
+        
+        cfg = nose.config.Config()
+        cfg.logStream = self.result_stream
+        cfg.debugLog = self.debug_stream
+        cfg.workingDir = options.test_dir
+        
+        self.testrunner = nose.core.TextTestRunner(stream=self.result_stream, descriptions=True, verbosity=2, config=config)
     
     def options(self, parser, env):
+        """
+        Register command line options
+        """
+        parser.add_option("--marvin-config", action="store",
+                          default=env.get('MARVIN_CONFIG', './datacenter.cfg'),
+                          dest="config",
+                          help="Marvin's configuration file where the datacenter information is specified [MARVIN_CONFIG]")
+        parser.add_option("--result-log", action="store",
+                          default=env.get('RESULT_LOG', 'result.log'),
+                          dest="result_log",
+                          help="The path to the results file where test summary will be written to [RESULT_LOG]")
+        parser.add_option("--client-log", action="store",
+                          default=env.get('DEBUG_LOG', 'debug.log'),
+                          dest="debug_log",
+                          help="The path to the testcase debug logs [DEBUG_LOG]")
+        parser.add_option("--load", action="store_true", default=False, dest="load",
+                          help="Only load the deployment configuration given")
+        
         Plugin.options(self, parser, env)
  
     def __init__(self):
         Plugin.__init__(self)
         
+    def prepareTestRunner(self, runner):
+        return self.testrunner
+    
     def wantClass(self, cls):
         if issubclass(cls, cloudstackTestCase):
             return True
@@ -36,15 +87,10 @@ class MarvinPlugin(Plugin):
         if client:
             self.testclient = client
 
-    def setClientLog(self, clientlog):
-        if clientlog:
-            self.log = clientlog
-
     def _injectClients(self, test):
-        testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__class__.__name__)
-        fh = logging.FileHandler(self.log) 
-        fh.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s"))
-        testcaselogger.addHandler(fh)
+        testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__name__)
+        self.debug_stream.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s"))
+        testcaselogger.addHandler(self.debug_stream)
         testcaselogger.setLevel(logging.DEBUG)
         
         setattr(test, "testClient", self.testclient)
@@ -52,3 +98,4 @@ class MarvinPlugin(Plugin):
         setattr(test, "clstestclient", self.testclient)
         if hasattr(test, "UserName"):
             self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType)
+            

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/13857700/tools/marvin/marvin/setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/setup.py b/tools/marvin/marvin/setup.py
new file mode 100644
index 0000000..83977f4
--- /dev/null
+++ b/tools/marvin/marvin/setup.py
@@ -0,0 +1,29 @@
+import os
+from setuptools import setup
+
+def read(fname):
+    return open(os.path.join(os.path.dirname(__file__), fname)).read().strip()
+
+VERSION = '0.1.0'
+
+setup(
+    name = "marvin-nose",
+    version = VERSION,
+    author = "Prasanna Santhanam",
+    author_email = "Prasanna.Santhanam@citrix.com",
+    description = "Run tests written using CloudStack's Marvin testclient",
+    license = 'ASL 2.0',
+    classifiers = [
+        "Intended Audience :: Developers",
+        "Topic :: Software Development :: Testing",
+        "Programming Language :: Python",
+        ],
+
+    py_modules = ['marvinPlugin'],
+    zip_safe = False,
+    
+    entry_points = {
+        'nose.plugins': ['marvinPlugin = marvinPlugin:MarvinPlugin']
+        },
+    install_requires = ['nose', 'marvin'],
+)