You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by sa...@apache.org on 2014/09/01 14:30:41 UTC
git commit: updated refs/heads/master to 6bd5041
Repository: cloudstack
Updated Branches:
refs/heads/master 10391c9b4 -> 6bd5041ff
Adding first cut(draft) for marvincli
Signed-off-by: Santhosh Edukulla <sa...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/6bd5041f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/6bd5041f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/6bd5041f
Branch: refs/heads/master
Commit: 6bd5041ff01bb58c31ce3e76b1ea4a01b87998a8
Parents: 10391c9
Author: Santhosh Edukulla <sa...@gmail.com>
Authored: Mon Sep 1 17:55:51 2014 +0530
Committer: Santhosh Edukulla <sa...@gmail.com>
Committed: Mon Sep 1 18:00:20 2014 +0530
----------------------------------------------------------------------
tools/marvin/marvin/deployAndRun.py | 485 ++++++++++++++++++++--------
tools/marvin/marvin/marvinInit.py | 20 +-
tools/marvin/marvin/tcExecuteEngine.py | 65 ++--
tools/marvin/setup.py | 3 +-
4 files changed, 397 insertions(+), 176 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6bd5041f/tools/marvin/marvin/deployAndRun.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py
index 9f392e5..611e167 100644
--- a/tools/marvin/marvin/deployAndRun.py
+++ b/tools/marvin/marvin/deployAndRun.py
@@ -15,153 +15,362 @@
# specific language governing permissions and limitations
# under the License.
-from .tcExecuteEngine import TestCaseExecuteEngine
import sys
import os
-import traceback
-import time
-from argparse import ArgumentParser
-from .marvinInit import MarvinInit
+from optparse import OptionParser
+import cmd
+import random
+from marvin.marvinInit import MarvinInit
+from marvin.deployDataCenter import DeployDataCenters
+from marvin.cloudstackException import GetDetailExceptionInfo
+from marvin.codegenerator import CodeGenerator
from marvin.codes import (SUCCESS,
FAILED,
- EXCEPTION,
- UNKNOWN_ERROR
+ EXCEPTION
)
+from marvin.tcExecuteEngine import TestCaseExecuteEngine
-parser = None
-
-
-def printAndExit():
- '''
- Prints pretty message for parser and exit
- '''
- global parser
- if parser is not None:
- parser.print_usage()
- exit(1)
-
-
-def parseAndCheck():
- '''
- Parses,reads the options and verifies for the config file
- '''
- global parser
- parser = ArgumentParser()
-
- parser.add_argument("-d", "--tcpath", dest="tcpath",
- help="the test case directory or file path")
- parser.add_argument("-c", "--config", action="store",
- default="./datacenterCfg", dest="config",
- help="the path where the json config file generated,\
- by default is ./datacenterCfg")
- parser.add_argument("-l", "--load", dest="load", action="store_true",
- help="only load config, do not deploy,\
- it will only run testcase")
- parser.add_argument("-n", "--num", dest="number",
- help="how many times you want to run the tests")
-
- options = parser.parse_args()
- cfg_file = options.config
- tc_path = options.tcpath
- load_flag = options.load
- num_iter = 1 if options.number is None else int(options.number)
-
- '''
- Check if the config file is None or not and exit accordingly
- '''
- if cfg_file is None:
- printAndExit()
- return {"cfg_file": cfg_file,
- "load_flag": load_flag,
- "tc_path": tc_path,
- "num_iter": num_iter}
-
-
-def startMarvin(cfg_file, load_flag):
- '''
- Initialize the Marvin
- '''
- try:
- obj_marvininit = MarvinInit(cfg_file, load_flag)
- if obj_marvininit.init() == SUCCESS:
- testClient = obj_marvininit.getTestClient()
- tcRunLogger = obj_marvininit.getLogger()
- parsedConfig = obj_marvininit.getParsedConfig()
- debugStream = obj_marvininit.getDebugFile()
- return {"tc_client": testClient,
- "tc_runlogger": tcRunLogger,
- "tc_parsedcfg": parsedConfig,
- "tc_debugstream": debugStream}
- else:
- print "\nMarvin Initialization Failed"
- exit(1)
- except Exception as e:
- print "\n Exception occurred while starting Marvin %s" % str(e)
- exit(1)
-
-
-def runTCs(num_iter, inp1, inp2):
- '''
- Run Test Cases based upon number of iterations
- '''
- n = 0
- while(n < num_iter):
- engine = TestCaseExecuteEngine(inp2["tc_client"],
- inp2["tc_parsedcfg"],
- inp2["tc_runlogger"],
- inp2["tc_debugstream"])
- if inp1["tc_file"] is not None:
- engine.loadTestsFromFile(inp1["tc_file"])
- else:
- engine.loadTestsFromDir(inp1["tc_dir"])
+class MarvinCliHelp(object):
+
+ @classmethod
+ def do_printhelp(cls):
+ print "\n1. for building marvin from spec file and installing."
+ cls.help_build_and_install()
+ print "\n2. for syncing apis and installing marvin."
+ cls.help_sync_and_install()
+ print "\n3. for deploying a datacenter"
+ cls.help_deploydc()
+ print "\n4. for running test cases"
+ cls.help_runtest()
+ print "\n5. for deploying a datacenter (and) running tests"
+ cls.help_deploydc_and_runtest()
+ print "\n6. for generating apis from spec file"
+ cls.help_generateapis_from_apispecfile()
+ print "\n7. for generating apis from end point"
+ cls.help_generateapis_from_endpoint()
+ print "\n8. for printing marvincli version"
+ cls.help_printversion()
+
+ @classmethod
+ def print_msg(cls, msg):
+ print ShellColor.BOLD + ShellColor.RED + msg + ShellColor.END
+
+ @classmethod
+ def help_printversion(cls):
+ cls.print_msg("marvincli -v or --version")
+
+ @classmethod
+ def help_deploydc(cls):
+ cls.print_msg(
+ "marvincli [deploydc] \n\t[config-file=<marvin-config-file EX: advanced.cfg file>]")
+
+ @classmethod
+ def help_deploydc_and_runtest(cls, deploy=False):
+ msg = "marvincli [deploydc_and_runtest] \n\t[config-file=<path_to_marvin_cfg> \n\ttc-path=<test suite or test suite folder path>" \
+ "\n\tzone=<name of the zone> \n\thyp-type=<hypervisor_type> " \
+ "\n\trequired_hardware=<true\\false>]"
+ cls.print_msg(msg)
+
+ @classmethod
+ def help_generateapis_from_apispecfile(cls):
+ cls.print_msg(
+ "marvincli [generateapis_from_apispecfile] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-spec-file=<api spec file EX: /etc/cloud/cli/commands.xml>]")
+
+ @classmethod
+ def help_generateapis_from_endpoint(cls):
+ cls.print_msg(
+ "marvincli [generateapis_from_endpoint] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS Endpoint ip EX: localhost>]")
+
+ @classmethod
+ def help_runtest(cls):
+ cls.print_msg(
+ "marvincli [runtest] \n\t[config-file=<path_to_marvin_config> \n\ttc-path=test/integration/smoke \n\trequired_hardware=<true\\false> \n\tzone=<name of zone> \n\thyp-type=<xenserver\\kvm\\vmware> etc]")
+
+ @classmethod
+ def help_sync_and_install(cls):
+ cls.print_msg(
+ "marvincli [sync_and_install] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS installed host ip EX: localhost>]")
+
+ @classmethod
+ def help_build_and_install(cls):
+ cls.print_msg(
+ "marvincli [build_and_install] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-sync-file<api spec file generated by cs EX: /etc/cloud/cli/commands.xml>]")
+
+
+class VerifyAndExit(object):
+
+ def __init__(self, msg):
+ self.msg = msg
+
+ def __call__(self, original_func):
+ def new_function(*args, **kwargs):
+ exit_check = False
+ try:
+ if original_func(*args, **kwargs) == FAILED:
+ exit_check = True
+ except Exception as e:
+ print "---", e
+ exit_check = True
+ finally:
+ if exit_check:
+ print "==== %s ====" % self.msg
+ MarvinCliHelp.do_printhelp()
+ sys.exit(1)
+ return new_function
+
+
+class MarvinCliCommands(object):
+ cmds_info = {'deploydc': {'options': ['config-file'], 'help': 'config-file=<marvin-config-file EX: advanced.cfg file>'},
+ 'deploydc_and_runtest': {'options': ['config-file', 'tc-path', 'zone', 'hyp-type', 'required_hardware'], 'help': ''},
+ 'generateapis_from_endpoint': {'options': '', 'help': '[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS Endpoint ip EX: localhost>]'},
+ 'generateapis_from_apispecfile': {'options': '', 'help': '[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-spec-file=<api spec file EX: /etc/cloud/cli/commands.xml>]'},
+ 'runtest': {'options': '', 'help': '[config-file=<path_to_marvin_config> \n\ttc-path=test/integration/smoke \n\trequired_hardware=<true\\false> \n\tzone=<name of zone> \n\thyp-type=<xenserver\\kvm\\vmware> etc]'},
+ 'sync_and_install': {'options': ['sync_and_install'], 'help': '[marvincli sync_and_install cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS installed host ip EX: localhost>]'},
+ 'build_and_install': {'options': ['build_and_install'], 'help': '[marvincli build_and_install cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-sync-file<api spec file generated by cs EX: /etc/cloud/cli/commands.xml>]'},
+ 'version': {'options': '', 'help': ''}
+ }
+
+
+class ShellColor(object):
+ BLUE = '\033[94m'
+ GREEN = '\033[92m'
+ YELLOW = '\033[93m'
+ RED = '\033[91m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+ END = '\033[0m'
+ ITALICS = '\x1B[3m'
+
+#VERSION = "4.5.0-SNAPSHOT"
+
+
+class MarvinCli(cmd.Cmd, object):
+
+ def __init__(self):
+ self.__configFile = None
+ self.__deployFlag = False
+ self.__zone = None
+ self.__hypervisorType = None
+ self.__tcPath = None
+ self.__testClient = None
+ self.__tcRunLogger = None
+ self.__parsedConfig = None
+ self.__resultStream = None
+ self.__logFolderPath = None
+ self.__testRunner = None
+ self.__requiredHw = False
+ self.__csFolder = "."
+ cmd.Cmd.__init__(self)
+
+ @VerifyAndExit("Invalid input options, please check")
+ def parse_input_deploy(self, inputs=None):
+ '''
+ Parses,reads the options and verifies for the config file
+ '''
+ if inputs:
+ out_dict = {}
+ args = inputs.strip().split(' ')
+ for item in args:
+ (key, value) = item.split('=')
+ out_dict[key] = value
+ self.__configFile = out_dict.get('config-file', '')
+ if not self.__configFile:
+ return FAILED
+ print "\n==== Parsing Input Options Successful ===="
+ return SUCCESS
+ return FAILED
+
+ @VerifyAndExit("Invalid input options, please check")
+ def parse_input_runtcs(self, inputs):
+ '''
+ Parses,reads the options and verifies for the config file
+ '''
+ if inputs:
+ out_dict = {}
+ args = inputs.strip().split(' ')
+ for item in args:
+ (key, value) = item.split('=')
+ out_dict[key] = value
+ self.__configFile = out_dict.get('config-file', None)
+ self.__deployFlag = out_dict.get('deploy', False)
+ self.__zone = out_dict.get("zone", None)
+ self.__hypervisorType = out_dict.get("hyp-type", None)
+ self.__tcPath = out_dict.get("tc-path",)
+ self.__requiredHw = out_dict.get("required-hardware")
+ if not all([self.__tcPath, self.__configFile]):
+ return FAILED
+ print "\n==== Parsing Input Options Successful ===="
+ return SUCCESS
+ return FAILED
+
+ @VerifyAndExit("Marvin initialization failed, please check")
+ def start_marvin(self):
+ '''
+ Initialize the Marvin
+ '''
+ try:
+ obj_marvininit = MarvinInit(config_file=self.__configFile,
+ deploy_dc_flag=self.__deployFlag,
+ zone=self.__zone,
+ hypervisor_type=self.__hypervisorType,
+ user_logfolder_path=None)
+ if obj_marvininit and obj_marvininit.init() == SUCCESS:
+ self.__testClient = obj_marvininit.getTestClient()
+ self.__tcRunLogger = obj_marvininit.getLogger()
+ self.__parsedConfig = obj_marvininit.getParsedConfig()
+ self.__resultStream = obj_marvininit.getResultFile()
+ self.__logFolderPath = obj_marvininit.getLogFolderPath()
+ return SUCCESS
+ return FAILED
+ except Exception as e:
+ print "====Exception Occurred under start_marvin: %s ====" % \
+ GetDetailExceptionInfo(e)
+ return FAILED
+
+ def run_test_suites(self):
+ print "\n==== Started Running Test Cases ===="
+ xunit_out_path = "/tmp/marvin_xunit_out" + \
+ str(random.randrange(1, 10000)) + ".xml"
+ marvin_tc_run_cmd = "nosetests-2.7 -s --with-marvin --marvin-config=%s --with-xunit --xunit-file=%s %s -a tags=advanced, required_hardware=%s --zone=%s --hypervisor=%s"
+ if os.path.isfile(self.__tcPath):
+ marvin_tc_run_cmd = marvin_tc_run_cmd % (self.__configFile,
+ xunit_out_path, self.__requiredHw, self.__zone, self.__hypervisorType)
+ if os.path.isdir(self.__tcPath):
+ marvin_tc_run_cmd = marvin_tc_run_cmd % (self.__configFile,
+ xunit_out_path, self.__requiredHw, self.__zone, self.__hypervisorType)
+ os.system(marvin_tc_run_cmd)
+ '''
+ engine = TestCaseExecuteEngine(self.__testClient,
+ self.__parsedConfig,
+ tc_logger=self.__tcRunLogger)
+ if os.path.isfile(self.__tcPath):
+ engine.loadTestsFromFile(self.__tcPath)
+ elif os.path.isdir(self.__tcPath):
+ engine.loadTestsFromDir(self.__tcPath)
engine.run()
- n = n + 1
-
-
-def checkTCPath(tc_path):
- '''
- Verifies if the tc_path is a folder or file and its existence
- '''
- ret = {"tc_file": None, "tc_dir": None}
- check = True
- if tc_path is None:
- printAndExit()
- else:
- if os.path.isfile(tc_path):
- ret["tc_file"] = tc_path
- elif os.path.isdir(tc_path):
- ret["tc_dir"] = tc_path
+ '''
+ print "\n==== Running Test Cases Successful ===="
+
+ def do_deploy(self, args):
+ self.__deployFlag = True
+ self.parse_input_deploy(inputs=args)
+ self.start_marvin()
+
+ def do_deploydc_and_runtest(self, args):
+ self.do_deploy(inputs=args)
+ self.parse_input_runtcs()
+ self.run_test_suites()
+
+ def do_generateapis_from_apispecfile(self, args):
+ api_spec_file = "/etc/cloud/cli/commands.xml"
+ cs_api_folder = "."
+ if args:
+ inp = args.strip().split(' ')
+ for items in inp:
+ (key, value) = items.split('=')
+ if key.lower() == 'api-spec-file':
+ if os.path.exists(value):
+ api_spec_file = value
+ elif not os.path.exists(api_spec_file):
+ print "=== Mentioned api spec file :%s does not exists ===" % str(api_spec_file)
+ sys.exit(1)
+ if key.lower() == 'cs-folder-path':
+ cs_api_folder = self.create_marvin_api_folder(value)
+ cg = CodeGenerator(cs_api_folder)
+ if api_spec_file:
+ try:
+ cg.generateCodeFromXML(api_spec_file)
+ return
+ except Exception as e:
+ print "==== Generating apis from api spec file failed: %s ====" % str(e.message())
+ sys.exit(1)
+ sys.exit(1)
+
+ def create_marvin_api_folder(self, cs_folder_path='.'):
+ cs_api_folder = cs_folder_path + "/tools/marvin/marvin/cloudstackAPI"
+ if os.path.exists(cs_api_folder):
+ os.rmdir(cs_api_folder)
else:
- check = False
- if check is False:
- print"\nTC Path is Invalid.So Exiting"
- exit(1)
+ os.makedirs(cs_api_folder)
+ return cs_api_folder
- return ret
+ def do_generateapis_from_endpoint(self, args):
+ endpoint_url = 'http://%s:8096/client/api?command=listApis&\
+response=json'
+ cs_api_folder = "."
+ if args:
+ inp = args.strip().split(' ')
+ for items in inp:
+ (key, value) = items.split('=')
+ if key.lower() == 'endpoint':
+ cs_end_point = value
+ if key.lower() == 'cs-folder-path':
+ cs_api_folder = self.create_marvin_api_folder(value)
+ cg = CodeGenerator(cs_api_folder)
+ if cs_end_point:
+ try:
+ endpoint_url = endpoint_url % str(cs_end_point)
+ cg.generateCodeFromJSON(endpoint_url)
+ return
+ except Exception as e:
+ print "==== Generating apis from end point failed: %s ====" % str(e.message())
+ sys.exit(1)
+ sys.exit(1)
-if __name__ == "__main__":
+ def do_runtest(self, args):
+ self.parse_input_runtcs(args)
+ self.start_marvin()
+ self.run_test_suites()
- '''
- 1. Parse and Check
- '''
- out1 = parseAndCheck()
- print "\nStep1 :Parsing Options And Check Went Fine"
-
- '''
- 2. Start Marvin
- '''
- out2 = startMarvin(out1["cfg_file"], out1["load_flag"])
- print "\nStep2: Marvin Initialization Went Fine"
-
- '''
- 3. Check TC folder or Module and Path existence
- '''
- out3 = checkTCPath(out1["tc_path"])
- print "\nStep3: TC Path Check Went Fine"
-
- '''
- 4. Run TCs
- '''
- runTCs(out1["num_iter"], out3, out2)
- print "\nStep4: TC Running Finished"
+ def install_marvin(self):
+ if self.__csFolder:
+ marvin_setup_file_path = self.__csFolder + "/tools/marvin/setup.py"
+ # step2: Build and install the Marvin
+ try:
+ os.system("python %s install" % str(marvin_setup_file_path))
+ except Exception as e:
+ print "==== Marvin Installation Failed ===="
+ print "==== Marvin Installed Successfully ===="
+
+ def do_build_and_install(self, args):
+ # step1: Generate the apis from spec file first
+ self.do_generateapis_from_apispecfile(args)
+ self.install_marvin()
+
+ def do_sync_and_install(self, args):
+ # step1: Generate the apis from spec file first
+ self.do_generateapis_from_endpoint(args)
+ self.install_marvin()
+
+
+class MarvinCliParser(OptionParser):
+
+ def format_help(self, formatter=None):
+ if formatter is None:
+ formatter = self.formatter
+ print MarvinCliHelp.print_msg("Usage: marvincli [cmd] [options].See, the below cmds for more information \n\n")
+ print MarvinCliHelp.do_printhelp()
+ return "\n===========================================================================\n"
+
+
+def main():
+ parser = MarvinCliParser()
+ parser.add_option("-v", "--version",
+ action="store_true", dest="version", default=False,
+ help="prints marvin cli version information")
+ (options, args) = parser.parse_args()
+ if options.version:
+ MarvinCliHelp.help_printversion()
+ sys.exit(0)
+ if len(sys.argv) > 1:
+ if sys.argv[1].lower() in ["deploydc", "deploydc_and_runtest", "generateapis_from_endpoint",
+ "generateapis_from_apispecfile", "runtest", "sync_and_install", "build_and_install"]:
+ MarvinCli().onecmd(' '.join(args))
+ else:
+ print "\n==== Invalid Command ===="
+ sys.exit(1)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6bd5041f/tools/marvin/marvin/marvinInit.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinInit.py b/tools/marvin/marvin/marvinInit.py
index 56ea509..e888484 100644
--- a/tools/marvin/marvin/marvinInit.py
+++ b/tools/marvin/marvin/marvinInit.py
@@ -40,7 +40,7 @@ import os
class MarvinInit:
def __init__(self, config_file,
- deploy_dc_flag=None,
+ deploy_dc_flag=False,
test_mod_name="deploydc",
zone=None,
hypervisor_type=None,
@@ -109,12 +109,19 @@ class MarvinInit:
'''
try:
if not self.__hypervisorType:
- self.__hypervisorType = XEN_SERVER
+ if self.__parsedConfig and self.__parsedConfig.zones is not None:
+ for zone in self.__parsedConfig.zones:
+ for pod in zone.pods and pod is not None:
+ for cluster in pod.clusters and cluster is not None:
+ self.__hypervisorType = cluster.hypervisor
+ break
if not self.__zoneForTests:
if self.__parsedConfig and self.__parsedConfig.zones is not None:
for zone in self.__parsedConfig.zones:
self.__zoneForTests = zone.name
break
+ if not self.__hypervisorType:
+ self.__hypervisorType = XEN_SERVER
return SUCCESS
except Exception as e:
print "\n Exception Occurred Under init " \
@@ -133,13 +140,16 @@ class MarvinInit:
@Output : SUCCESS or FAILED
'''
try:
+ print "\n==== Marvin Init Started ===="
if ((self.__parseConfig() != FAILED) and
(self.__setHypervisorAndZoneInfo())and
(self.__setTestDataPath() != FAILED) and
(self.__initLogging() != FAILED) and
(self.__createTestClient() != FAILED) and
(self.__deployDC() != FAILED)):
+ print "\n==== Marvin Init Successful ===="
return SUCCESS
+ print "\n==== Marvin Init Failed ===="
return FAILED
except Exception as e:
print "\n Exception Occurred Under init " \
@@ -232,10 +242,8 @@ class MarvinInit:
self.__parsedConfig,
self.__tcRunLogger)
ret = deploy_obj.deploy()
- if ret == SUCCESS:
- print "Deploy DC Successful"
- else:
- print "Deploy DC Failed"
+ if ret != SUCCESS:
+ print "==== Deploy DC Failed ===="
return ret
except Exception as e:
print "\n Exception Occurred Under __deployDC : %s" % \
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6bd5041f/tools/marvin/marvin/tcExecuteEngine.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/tcExecuteEngine.py b/tools/marvin/marvin/tcExecuteEngine.py
index e2f4d11..11b5d09 100644
--- a/tools/marvin/marvin/tcExecuteEngine.py
+++ b/tools/marvin/marvin/tcExecuteEngine.py
@@ -24,50 +24,53 @@ from functools import partial
class TestCaseExecuteEngine(object):
- def __init__(self, testclient, config, tc_logger=None, debug_stream=None):
+ def __init__(self, testclient, config, tc_logger=None,
+ debug_stream=sys.stdout):
"""
- Initialize the testcase execution engine, just the basics here
- @var testcaseLogFile: client log file
- @var testResultLogFile: summary report file
+ Initialize the testcase execution engine
"""
- self.testclient = testclient
- self.config = config
- self.tcRunLogger = tc_logger
- self.debugStream = debug_stream
- self.loader = unittest.loader.TestLoader()
- self.suite = None
+ self.__testClient = testclient
+ self.__parsedConfig = config
+ self.__tcRunLogger = tc_logger
+ self.__debugStream = debug_stream
+ self.__loader = unittest.loader.TestLoader()
+ self.__suite = None
- def loadTestsFromDir(self, testDirectory):
+ def loadTestsFromDir(self, test_directory):
""" Load the test suites from a package with multiple test files """
- self.suite = self.loader.discover(testDirectory)
- self.injectTestCase(self.suite)
+ self.__suite = self.__loader.discover(test_directory)
+ self.injectTestCase(self.__suite)
def loadTestsFromFile(self, file_name):
""" Load the tests from a single script/module """
if os.path.isfile(file_name):
- self.suite = self.loader.discover(os.path.dirname(file_name),
- os.path.basename(file_name))
- self.injectTestCase(self.suite)
+ self.__suite = self.__loader.discover(os.path.dirname(file_name),
+ os.path.basename(file_name))
+ self.injectTestCase(self.__suite)
- def injectTestCase(self, testSuites):
- for test in testSuites:
+ def injectTestCase(self, test_suites):
+ for test in test_suites:
if isinstance(test, unittest.BaseTestSuite):
self.injectTestCase(test)
else:
# inject testclient and logger into each unittest
- self.tcRunLogger.name = test.__str__()
- setattr(test, "testClient", self.testclient)
- setattr(test, "config", self.config)
- setattr(test, "debug", self.tcRunLogger.debug)
- setattr(test.__class__, "clstestclient", self.testclient)
+ setattr(test, "debug", self.__tcRunLogger.debug)
+ setattr(test, "info", self.__tcRunLogger.info)
+ setattr(test, "warn", self.__tcRunLogger.warning)
+ setattr(test, "error", self.__tcRunLogger.error)
+ setattr(test, "clstestclient", self.__testClient)
+ setattr(test, "testClient", self.__testClient)
+ setattr(test, "config", self.__parsedConfig)
if hasattr(test, "user"):
- # attribute when test is entirely executed as user
- self.testclient.\
- getUserApiClient(test.UserName,
- test.DomainName,
- test.AcctType)
+ # when the class-level attr applied. all test runs as
+ # 'user'
+ self.__testClient.getUserApiClient(test.UserName,
+ test.DomainName,
+ test.AcctType)
def run(self):
- if self.suite:
- unittest.TextTestRunner(stream=self.debugStream,
- verbosity=2).run(self.suite)
+ if self.__suite:
+ print "\n==== Test Suite :%s Started ====" % (str(self.__suite))
+ unittest.TextTestRunner(stream=self.__debugStream,
+ verbosity=2).run(self.__suite)
+ print "\n==== Test Suite :%s Finished ====" % (str(self.__suite))
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6bd5041f/tools/marvin/setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py
index 03e53c9..2a44a16 100644
--- a/tools/marvin/setup.py
+++ b/tools/marvin/setup.py
@@ -55,6 +55,7 @@ setup(name="Marvin",
py_modules=['marvin.marvinPlugin'],
zip_safe=False,
entry_points={
- 'nose.plugins': ['marvinPlugin = marvin.marvinPlugin:MarvinPlugin']
+ 'nose.plugins': ['marvinPlugin = marvin.marvinPlugin:MarvinPlugin'],
+ 'console_scripts': ['marvincli = marvin.deployAndRun:main']
},
)