mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
marvin: argparse enhancement and unit-test-xml-reporting dependency removed
1. deployAndRun will use the more modern argparse module 2. improving logging within the remoteSSHClient, moving to debug and default logging to INFO 3. removing dependance on the xmlrunner. use nose --with-xunit instead Signed-off-by: Prasanna Santhanam <tsp@apache.org>
This commit is contained in:
parent
7ee602beaf
commit
3075d0cf56
@ -16,7 +16,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import xmlrunner
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
@ -27,7 +26,7 @@ def testCaseLogger(message, logger=None):
|
|||||||
logger.debug(message)
|
logger.debug(message)
|
||||||
|
|
||||||
class TestCaseExecuteEngine(object):
|
class TestCaseExecuteEngine(object):
|
||||||
def __init__(self, testclient, config, testcaseLogFile=None, testResultLogFile=None, format="text", xmlDir="xml-reports"):
|
def __init__(self, testclient, config, testcaseLogFile=None, testResultLogFile=None):
|
||||||
"""
|
"""
|
||||||
Initialize the testcase execution engine, just the basics here
|
Initialize the testcase execution engine, just the basics here
|
||||||
@var testcaseLogFile: client log file
|
@var testcaseLogFile: client log file
|
||||||
@ -38,7 +37,6 @@ class TestCaseExecuteEngine(object):
|
|||||||
self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
|
self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
|
||||||
self.loader = unittest.loader.TestLoader()
|
self.loader = unittest.loader.TestLoader()
|
||||||
self.suite = None
|
self.suite = None
|
||||||
self.format = format
|
|
||||||
|
|
||||||
if testcaseLogFile is not None:
|
if testcaseLogFile is not None:
|
||||||
self.logfile = testcaseLogFile
|
self.logfile = testcaseLogFile
|
||||||
@ -56,9 +54,7 @@ class TestCaseExecuteEngine(object):
|
|||||||
self.testResultLogFile = fp
|
self.testResultLogFile = fp
|
||||||
else:
|
else:
|
||||||
self.testResultLogFile = sys.stdout
|
self.testResultLogFile = sys.stdout
|
||||||
if self.format == "xml" and (xmlDir is not None):
|
|
||||||
self.xmlDir = xmlDir
|
|
||||||
|
|
||||||
def loadTestsFromDir(self, testDirectory):
|
def loadTestsFromDir(self, testDirectory):
|
||||||
""" Load the test suites from a package with multiple test files """
|
""" Load the test suites from a package with multiple test files """
|
||||||
self.suite = self.loader.discover(testDirectory)
|
self.suite = self.loader.discover(testDirectory)
|
||||||
@ -92,7 +88,4 @@ class TestCaseExecuteEngine(object):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.suite:
|
if self.suite:
|
||||||
if self.format == "text":
|
unittest.TextTestRunner(stream=self.testResultLogFile, verbosity=2).run(self.suite)
|
||||||
unittest.TextTestRunner(stream=self.testResultLogFile, verbosity=2).run(self.suite)
|
|
||||||
elif self.format == "xml":
|
|
||||||
xmlrunner.XMLTestRunner(output=self.xmlDir).run(self.suite)
|
|
||||||
|
|||||||
@ -17,22 +17,22 @@
|
|||||||
|
|
||||||
import deployDataCenter
|
import deployDataCenter
|
||||||
import TestCaseExecuteEngine
|
import TestCaseExecuteEngine
|
||||||
from optparse import OptionParser
|
from argparse import ArgumentParser
|
||||||
import os
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
parser = OptionParser() #TODO: deprecate and use the argparse module
|
parser = ArgumentParser()
|
||||||
|
|
||||||
parser.add_option("-c", "--config", action="store", default="./datacenterCfg", dest="config", help="the path where the json config file generated, by default is ./datacenterCfg")
|
parser.add_argument("-d", "--directory", dest="testCaseFolder", help="the test case directory")
|
||||||
parser.add_option("-d", "--directory", dest="testCaseFolder", help="the test case directory")
|
parser.add_argument("-f", "--file", dest="module", help="run tests in the given file")
|
||||||
parser.add_option("-r", "--result", dest="result", help="test result log file")
|
parser.add_argument("-r", "--result", dest="result", help="test result log file", default='/tmp/t.log')
|
||||||
parser.add_option("-t", "--client", dest="testcaselog", help="test case log file")
|
parser.add_argument("-t", "--client", dest="testcaselog", help="test case log file", default='/tmp/r.log')
|
||||||
parser.add_option("-l", "--load", dest="load", action="store_true", help="only load config, do not deploy, it will only run testcase")
|
parser.add_argument("-c", "--config", action="store", default="./datacenterCfg", dest="config",
|
||||||
parser.add_option("-f", "--file", dest="module", help="run tests in the given file")
|
help="the path where the json config file generated, by default is ./datacenterCfg")
|
||||||
parser.add_option("-x", "--xml", dest="xmlrunner", help="use the xml runner to generate xml reports and path to store xml files")
|
parser.add_argument("-l", "--load", dest="load", action="store_true",
|
||||||
(options, args) = parser.parse_args()
|
help="only load config, do not deploy, it will only run testcase")
|
||||||
|
|
||||||
|
options = parser.parse_args()
|
||||||
|
|
||||||
testResultLogFile = None
|
testResultLogFile = None
|
||||||
if options.result is not None:
|
if options.result is not None:
|
||||||
testResultLogFile = options.result
|
testResultLogFile = options.result
|
||||||
@ -46,12 +46,6 @@ if __name__ == "__main__":
|
|||||||
else:
|
else:
|
||||||
deploy.deploy()
|
deploy.deploy()
|
||||||
|
|
||||||
fmt = "text"
|
|
||||||
xmlDir = None
|
|
||||||
if options.xmlrunner is not None:
|
|
||||||
xmlDir = options.xmlrunner
|
|
||||||
fmt = "xml"
|
|
||||||
|
|
||||||
if options.testCaseFolder is None:
|
if options.testCaseFolder is None:
|
||||||
if options.module is None:
|
if options.module is None:
|
||||||
parser.print_usage()
|
parser.print_usage()
|
||||||
@ -61,15 +55,13 @@ if __name__ == "__main__":
|
|||||||
TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
|
TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
|
||||||
deploy.getCfg(),
|
deploy.getCfg(),
|
||||||
testCaseLogFile,
|
testCaseLogFile,
|
||||||
testResultLogFile, fmt,
|
testResultLogFile)
|
||||||
xmlDir)
|
|
||||||
engine.loadTestsFromFile(options.module)
|
engine.loadTestsFromFile(options.module)
|
||||||
engine.run()
|
engine.run()
|
||||||
else:
|
else:
|
||||||
engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
|
engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
|
||||||
deploy.getCfg(),
|
deploy.getCfg(),
|
||||||
testCaseLogFile,
|
testCaseLogFile,
|
||||||
testResultLogFile,
|
testResultLogFile)
|
||||||
fmt, xmlDir)
|
|
||||||
engine.loadTestsFromDir(options.testCaseFolder)
|
engine.loadTestsFromDir(options.testCaseFolder)
|
||||||
engine.run()
|
engine.run()
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import logging
|
|||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
class remoteSSHClient(object):
|
class remoteSSHClient(object):
|
||||||
def __init__(self, host, port, user, passwd, retries = 10):
|
def __init__(self, host, port, user, passwd, retries = 10, log_lvl=logging.INFO):
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.user = user
|
self.user = user
|
||||||
@ -32,14 +32,14 @@ class remoteSSHClient(object):
|
|||||||
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
self.logger = logging.getLogger('sshClient')
|
self.logger = logging.getLogger('sshClient')
|
||||||
ch = logging.StreamHandler()
|
ch = logging.StreamHandler()
|
||||||
ch.setLevel(logging.DEBUG)
|
ch.setLevel(log_lvl)
|
||||||
self.logger.addHandler(ch)
|
self.logger.addHandler(ch)
|
||||||
|
|
||||||
retry_count = retries
|
retry_count = retries
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
self.ssh.connect(str(host),int(port), user, passwd)
|
self.ssh.connect(str(host),int(port), user, passwd)
|
||||||
self.logger.debug("connecting to server %s with user %s passwd %s"%(str(host), user, passwd))
|
self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
|
||||||
except paramiko.SSHException, sshex:
|
except paramiko.SSHException, sshex:
|
||||||
if retry_count == 0:
|
if retry_count == 0:
|
||||||
raise cloudstackException.InvalidParameterException(repr(sshex))
|
raise cloudstackException.InvalidParameterException(repr(sshex))
|
||||||
@ -52,7 +52,6 @@ class remoteSSHClient(object):
|
|||||||
|
|
||||||
def execute(self, command):
|
def execute(self, command):
|
||||||
stdin, stdout, stderr = self.ssh.exec_command(command)
|
stdin, stdout, stderr = self.ssh.exec_command(command)
|
||||||
self.logger.debug("sending command %s to host %s"%(command, str(self.host)))
|
|
||||||
output = stdout.readlines()
|
output = stdout.readlines()
|
||||||
errors = stderr.readlines()
|
errors = stderr.readlines()
|
||||||
results = []
|
results = []
|
||||||
@ -64,7 +63,7 @@ class remoteSSHClient(object):
|
|||||||
else:
|
else:
|
||||||
for strOut in output:
|
for strOut in output:
|
||||||
results.append(strOut.rstrip())
|
results.append(strOut.rstrip())
|
||||||
self.logger.debug("command %s returned %s"%(command, results))
|
self.logger.debug("{Cmd: %s via Host: %s} {returns: %s}"%(command, str(self.host), results))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def scp(self, srcFile, destPath):
|
def scp(self, srcFile, destPath):
|
||||||
|
|||||||
@ -41,7 +41,6 @@ def describeResources(config):
|
|||||||
z.name = 'Sandbox-%s'%(config.get('environment', 'hypervisor'))
|
z.name = 'Sandbox-%s'%(config.get('environment', 'hypervisor'))
|
||||||
z.networktype = 'Advanced'
|
z.networktype = 'Advanced'
|
||||||
z.guestcidraddress = '10.1.1.0/24'
|
z.guestcidraddress = '10.1.1.0/24'
|
||||||
z.vlan = config.get('cloudstack', 'zone.vlan')
|
|
||||||
|
|
||||||
vpcprovider = provider()
|
vpcprovider = provider()
|
||||||
vpcprovider.name = 'VpcVirtualRouter'
|
vpcprovider.name = 'VpcVirtualRouter'
|
||||||
@ -50,6 +49,7 @@ def describeResources(config):
|
|||||||
pn.name = "Sandbox-pnet"
|
pn.name = "Sandbox-pnet"
|
||||||
pn.traffictypes = [traffictype("Guest"), traffictype("Management"), traffictype("Public")]
|
pn.traffictypes = [traffictype("Guest"), traffictype("Management"), traffictype("Public")]
|
||||||
pn.providers.append(vpcprovider)
|
pn.providers.append(vpcprovider)
|
||||||
|
pn.vlan = config.get('cloudstack', 'zone.vlan')
|
||||||
|
|
||||||
z.physical_networks.append(pn)
|
z.physical_networks.append(pn)
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class TestSetupSuccess(cloudstackTestCase):
|
|||||||
retry = retry - 1
|
retry = retry - 1
|
||||||
delay(60) #wait a minute for retry
|
delay(60) #wait a minute for retry
|
||||||
self.assertNotEqual(retry, 0, "builtIn templates not ready in zone %s"%z.name)
|
self.assertNotEqual(retry, 0, "builtIn templates not ready in zone %s"%z.name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -65,8 +65,8 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>package</id>
|
<id>install</id>
|
||||||
<phase>package</phase>
|
<phase>install</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>exec</goal>
|
<goal>exec</goal>
|
||||||
</goals>
|
</goals>
|
||||||
@ -117,7 +117,42 @@
|
|||||||
<goals>
|
<goals>
|
||||||
<goal>exec</goal>
|
<goal>exec</goal>
|
||||||
</goals>
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<workingDirectory>${basedir}/marvin</workingDirectory>
|
||||||
|
<executable>/usr/local/bin/nosetests</executable>
|
||||||
|
<arguments>
|
||||||
|
<argument>--with-marvin</argument>
|
||||||
|
<argument>--marvin-config</argument>
|
||||||
|
<argument>${user.dir}/${marvin.config}</argument>
|
||||||
|
<argument>--load</argument>
|
||||||
|
<argument>-a</argument>
|
||||||
|
<argument>tags=simulator</argument>
|
||||||
|
<argument>${basedir}/../../test/integration/smoke/test_vm_life_cycle.py</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
<!--execution>
|
||||||
|
<id>pre-integration-test</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>exec</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<workingDirectory>${basedir}/marvin</workingDirectory>
|
||||||
|
<executable>python</executable>
|
||||||
|
<arguments>
|
||||||
|
<argument>deployAndRun.py</argument>
|
||||||
|
<argument>-c</argument>
|
||||||
|
<argument>${user.dir}/${marvin.config}</argument>
|
||||||
|
<argument>-t</argument>
|
||||||
|
<argument>/tmp/t.log</argument>
|
||||||
|
<argument>-r</argument>
|
||||||
|
<argument>/tmp/r.log</argument>
|
||||||
|
<argument>-f</argument>
|
||||||
|
<argument>${basedir}/marvin/testSetupSuccess.py</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution-->
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
@ -37,7 +37,6 @@ setup(name="Marvin",
|
|||||||
install_requires=[
|
install_requires=[
|
||||||
"mysql-connector-python",
|
"mysql-connector-python",
|
||||||
"paramiko",
|
"paramiko",
|
||||||
"nose",
|
"nose"
|
||||||
"unittest-xml-reporting>1.2"
|
],
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user