update my forked branch
diff --git a/TestON/core/Thread.py b/TestON/core/Thread.py
new file mode 100644
index 0000000..fcc06b5
--- /dev/null
+++ b/TestON/core/Thread.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+import threading
+
+
+class Thread( threading.Thread ):
+ def __init__( self, target=None, threadID=None, name="", args=(),
+ kwargs={} ):
+ super( Thread, self ).__init__()
+ self.threadID = threadID
+ self.name = name
+ self.target = target
+ self.args = args
+ self.kwargs = kwargs
+ self.result = None
+
+ def run( self ):
+ try:
+ if self.target is not None:
+ self.result = self.target( *self.args, **self.kwargs )
+ except Exception as e:
+ print "ThreadID:" + str( self.threadID ) + ", Name:" +\
+ self.name + "- something went wrong with " +\
+ str( self.target.im_class ) + "." +\
+ str( self.target.im_func ) + " method: "
+ print e
diff --git a/TestON/core/iniparser.py b/TestON/core/iniparser.py
index b952f2d..c350a20 100644
--- a/TestON/core/iniparser.py
+++ b/TestON/core/iniparser.py
@@ -48,7 +48,7 @@
try :
parsedInfo = ConfigObj(self.fileName)
return parsedInfo
- except :
+ except Exception:
print "There is no such file to parse "+fileName
else:
return 0
diff --git a/TestON/core/jsonparser.py b/TestON/core/jsonparser.py
index 8726e87..fea797a 100644
--- a/TestON/core/jsonparser.py
+++ b/TestON/core/jsonparser.py
@@ -21,7 +21,6 @@
'''
-import re
import json
class JsonParser:
'''
@@ -37,7 +36,7 @@
response_dict = {}
try :
response_dict = json.loads(json_response)
- except :
+ except Exception:
main.log.error("Json Parser is unable to parse the string")
return response_dict
@@ -50,7 +49,7 @@
json_response = {}
try :
json_response = json.dumps(response_dict)
- except :
+ except Exception:
main.log.error("Json Parser is unable to parse the string")
return json_response
'''
diff --git a/TestON/core/logger.py b/TestON/core/logger.py
index 80fe0de..e77d440 100644
--- a/TestON/core/logger.py
+++ b/TestON/core/logger.py
@@ -1,7 +1,7 @@
#/usr/bin/env python
'''
Created on 07-Jan-2013
-
+
@author: Raghav Kashyap(raghavkashyap@paxterrasolutions.com)
TestON is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with TestON. If not, see <http://www.gnu.org/licenses/>.
+ along with TestON. If not, see <http://www.gnu.org/licenses/>.
'''
@@ -27,7 +27,7 @@
class Logger:
'''
Add continuous logs and reports of the test.
-
+
@author: Raghav Kashyap(raghavkashyap@paxterrasolutions.com)
'''
def _printHeader(self,main) :
@@ -39,7 +39,7 @@
logmsg = logmsg + "\n\tReport Log File : " + main.ReportFileName + ""
for component in main.componentDictionary.keys():
logmsg = logmsg + "\n\t"+component+" Session Log : " + main.logdir+"/"+component+".session" + ""
-
+
logmsg = logmsg + "\n\tTest Script :" + path + "Tests/" + main.TEST + ".py"+ ""
logmsg = logmsg + "\n\tTest Params : " + path + "Tests/" + main.TEST + ".params" + ""
logmsg = logmsg + "\n\tTopology : " + path + "Tests/" +main.TEST + ".topo" + ""
@@ -49,11 +49,10 @@
values = re.sub("{", "\n\t", values)
values = re.sub("}", "\n\t", values)
logmsg = logmsg + values
-
logmsg = logmsg + "\n\n"+" " * 31+"+---------------+\n" +"-" * 29+" { Components Used } " +"-" * 29+"\n"+" " * 31+"+---------------+\n"
component_list = []
component_list.append(None)
-
+
# Listing the components in the order of test_target component should be first.
if type(main.componentDictionary) == dict:
for key in main.componentDictionary.keys():
@@ -61,64 +60,74 @@
component_list[0] = key+"-Test Target"
else :
component_list.append(key)
-
+
for index in range(len(component_list)) :
if index==0:
if component_list[index]:
logmsg+="\t"+component_list[index]+"\n"
elif index > 0 :
logmsg+="\t"+str(component_list[index])+"\n"
-
-
-
+
logmsg = logmsg + "\n\n"+" " * 30+"+--------+\n" +"-" * 28+" { Topology } "+"-" * 28 +"\n" +" " * 30+"+--------+\n"
values = "\n\t" + str(main.topology['COMPONENT'])
values = re.sub(",", "\n\t", values)
values = re.sub("{", "\n\t", values)
values = re.sub("}", "\n\t", values)
logmsg = logmsg + values
-
logmsg = logmsg + "\n"+"-" * 60+"\n"
-
+
# enter into log file all headers
logfile = open(main.LogFileName,"w+")
logfile.write (logmsg)
print logmsg
main.logHeader = logmsg
-
logfile.close()
-
+
#enter into report file all headers
main.reportFile = open(main.ReportFileName,"w+")
main.reportFile.write(logmsg)
main.reportFile.close()
-
+
+ #Sumamry file header
+ currentTime = str( main.STARTTIME.strftime("%d %b %Y %H:%M:%S") )
+ main.summaryFile = open( main.SummaryFileName, "w+" )
+ main.summaryFile.write( main.TEST + " at " + currentTime + "\n" )
+ main.summaryFile.close()
+
+ #wiki file header
+ currentTime = str( main.STARTTIME.strftime("%d %b %Y %H:%M:%S") )
+ main.wikiFile = open( main.WikiFileName, "w+" )
+ main.wikiFile.write( main.TEST + " at " + currentTime + "<p></p>\n" )
+ main.wikiFile.close()
+
def initlog(self,main):
'''
Initialise all the log handles.
'''
main._getTest()
- main.STARTTIME = datetime.datetime.now()
+ main.STARTTIME = datetime.datetime.now()
currentTime = re.sub("-|\s|:|\.", "_", str(main.STARTTIME.strftime("%d %b %Y %H:%M:%S")))
if main.logdir:
main.logdir = main.logdir+ "/"+main.TEST + "_" + currentTime
else:
main.logdir = main.logs_path + main.TEST + "_" + currentTime
-
+
os.mkdir(main.logdir)
-
+
main.LogFileName = main.logdir + "/" + main.TEST + "_" +str(currentTime) + ".log"
main.ReportFileName = main.logdir + "/" + main.TEST + "_" + str(currentTime) + ".rpt"
+ main.WikiFileName = main.logdir + "/" + main.TEST + "Wiki.txt"
+ main.SummaryFileName = main.logdir + "/" + main.TEST + "Summary.txt"
main.JenkinsCSV = main.logdir + "/" + main.TEST + ".csv"
-
+
#### Add log-level - Report
logging.addLevelName(9, "REPORT")
logging.addLevelName(7, "EXACT")
- logging.addLevelName(10, "CASE")
- logging.addLevelName(11, "STEP")
+ logging.addLevelName(11, "CASE")
+ logging.addLevelName(12, "STEP")
main.log = logging.getLogger(main.TEST)
- def report (msg):
+ def report(msg):
'''
Will append the report message to the logs.
'''
@@ -130,11 +139,32 @@
main.reportFile = open(main.ReportFileName,"a+")
main.reportFile.write(newmsg)
main.reportFile.close()
-
-
- main.log.report = report
-
- def exact (exmsg):
+
+ main.log.report = report
+
+ def summary( msg ):
+ '''
+ Will append the message to the txt file for the summary.
+ '''
+ main.log._log(6,msg,"OpenFlowAutoMattion","OFAutoMation")
+ main.summaryFile = open(main.SummaryFileName,"a+")
+ main.summaryFile.write(msg+"\n")
+ main.summaryFile.close()
+
+ main.log.summary = summary
+
+ def wiki( msg ):
+ '''
+ Will append the message to the txt file for the wiki.
+ '''
+ main.log._log(6,msg,"OpenFlowAutoMattion","OFAutoMation")
+ main.wikiFile = open(main.WikiFileName,"a+")
+ main.wikiFile.write(msg+"\n")
+ main.wikiFile.close()
+
+ main.log.wiki = wiki
+
+ def exact(exmsg):
'''
Will append the raw formatted message to the logs
'''
@@ -146,10 +176,9 @@
logfile.write("\n"+ str(exmsg) +"\n")
logfile.close()
print exmsg
-
- main.log.exact = exact
-
-
+
+ main.log.exact = exact
+
def case(msg):
'''
Format of the case type log defined here.
@@ -161,10 +190,10 @@
logfile.write("\n"+ str(newmsg) +"\n")
logfile.close()
print newmsg
-
+
main.log.case = case
-
- def step (msg):
+
+ def step(msg):
'''
Format of the step type log defined here.
'''
@@ -175,28 +204,57 @@
logfile.write("\n"+ str(newmsg) +"\n")
logfile.close()
print newmsg
-
- main.log.step = step
-
+
+ main.log.step = step
+
main.LogFileHandler = logging.FileHandler(main.LogFileName)
self._printHeader(main)
### initializing logging module and settig log level
main.log.setLevel(logging.INFO)
+ main.log.setLevel(logging.DEBUG) # Temporary
main.LogFileHandler.setLevel(logging.INFO)
-
+
# create console handler with a higher log level
main.ConsoleHandler = logging.StreamHandler()
main.ConsoleHandler.setLevel(logging.INFO)
+ main.ConsoleHandler.setLevel(logging.DEBUG) #Temporary
# create formatter and add it to the handlers
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ #formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ class MyFormatter( logging.Formatter ):
+ colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
+ 'blue': '\033[94m', 'green': '\033[92m',
+ 'yellow': '\033[93m', 'red': '\033[91m',
+ 'end': '\033[0m' }
+
+ FORMATS = {'DEFAULT': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'}
+ if COLORS: # NOTE:colors will only be loaded if command is run from one line
+ # IE: './cli.py run testname'
+ # This is to prevent issues with Jenkins parsing
+ # TODO: Make colors configurable
+ levels = { logging.ERROR : colors['red'] +
+ FORMATS['DEFAULT'] +
+ colors['end'],
+ logging.WARN : colors['yellow'] +
+ FORMATS['DEFAULT'] +
+ colors['end'],
+ logging.DEBUG : colors['purple'] +
+ FORMATS['DEFAULT'] +
+ colors['end'] }
+ FORMATS.update( levels )
+
+ def format( self, record ):
+ self._fmt = self.FORMATS.get( record.levelno,
+ self.FORMATS[ 'DEFAULT' ] )
+ return logging.Formatter.format( self, record )
+ formatter = MyFormatter()
main.ConsoleHandler.setFormatter(formatter)
main.LogFileHandler.setFormatter(formatter)
# add the handlers to logger
main.log.addHandler(main.ConsoleHandler)
main.log.addHandler(main.LogFileHandler)
-
+
def testSummary(self,main):
'''
testSummary will take care about the Summary of test.
@@ -208,12 +266,10 @@
main.TOTAL_TC_SUCCESS = 0
else:
main.TOTAL_TC_SUCCESS = str((main.TOTAL_TC_PASS*100)/main.TOTAL_TC_RUN)
-
if (main.TOTAL_TC_RUN == 0) :
main.TOTAL_TC_EXECPERCENT = 0
else :
main.TOTAL_TC_EXECPERCENT = str((main.TOTAL_TC_RUN*100)/main.TOTAL_TC_PLANNED)
-
testResult = "\n\n"+"*" * 37+"\n" + "\tTest Execution Summary\n" + "\n"+"*" * 37+" \n"
testResult = testResult + "\n Test Start : " + str(main.STARTTIME.strftime("%d %b %Y %H:%M:%S"))
testResult = testResult + "\n Test End : " + str(main.ENDTIME.strftime("%d %b %Y %H:%M:%S"))
@@ -225,7 +281,7 @@
testResult = testResult + "\n Total No Result : " + str(main.TOTAL_TC_NORESULT)
testResult = testResult + "\n Success Percentage : " + str(main.TOTAL_TC_SUCCESS) + "%"
testResult = testResult + "\n Execution Result : " + str(main.TOTAL_TC_EXECPERCENT) + "%"
-
+
#main.log.report(testResult)
main.testResult = testResult
main.log.exact(testResult)
@@ -237,24 +293,32 @@
logfile.write(",".join( [str(int(main.TOTAL_TC_FAIL)), str(int(main.TOTAL_TC_PASS)), str(int(main.TOTAL_TC_PLANNED))] ))
logfile.close()
-
-
-
def updateCaseResults(self,main):
'''
Update the case result based on the steps execution and asserting each step in the test-case
'''
case = str(main.CurrentTestCaseNumber)
-
- if main.testCaseResult[case] == 2:
+ currentResult = main.testCaseResult.get(case, 2)
+
+ if currentResult == 2:
main.TOTAL_TC_RUN = main.TOTAL_TC_RUN + 1
main.TOTAL_TC_NORESULT = main.TOTAL_TC_NORESULT + 1
main.log.exact("\n "+"*" * 29+"\n" + "\n Result: No Assertion Called \n"+"*" * 29+"\n")
- elif main.testCaseResult[case] == 1:
+ line = "Case "+case+": "+main.CurrentTestCase+" - No Result"
+ elif currentResult == 1:
main.TOTAL_TC_RUN = main.TOTAL_TC_RUN + 1
main.TOTAL_TC_PASS = main.TOTAL_TC_PASS + 1
main.log.exact("\n"+"*" * 29+"\n Result: Pass \n"+"*" * 29+"\n")
- elif main.testCaseResult[case] == 0:
+ line = "Case "+case+": "+main.CurrentTestCase+" - PASS"
+ elif currentResult == 0:
main.TOTAL_TC_RUN = main.TOTAL_TC_RUN + 1
main.TOTAL_TC_FAIL = main.TOTAL_TC_FAIL + 1
main.log.exact("\n"+"*" * 29+"\n Result: Failed \n"+"*" * 29+"\n")
+ line = "Case "+case+": "+main.CurrentTestCase+" - FAIL"
+ else:
+ main.log.error( " Unknown result of case " + case +
+ ". Result was: " + currentResult )
+ line = "Case "+case+": "+main.CurrentTestCase+" - ERROR"
+ main.log.wiki( "<h3>" + line + "</h3>" )
+ main.log.summary( line )
+
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index 8934e50..a15bb8c 100644
--- a/TestON/core/teston.py
+++ b/TestON/core/teston.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
'''
Created on 22-Oct-2012
-
+
@author: Anil Kumar (anilkumar.s@paxterrasolutions.com)
@@ -16,7 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with TestON. If not, see <http://www.gnu.org/licenses/>.
+ along with TestON. If not, see <http://www.gnu.org/licenses/>.
@@ -31,6 +31,7 @@
import __builtin__
import new
import xmldict
+import importlib
module = new.module("test")
import openspeak
global path, drivers_path, core_path, tests_path,logs_path
@@ -46,52 +47,50 @@
sys.path.append(tests_path)
from core.utilities import Utilities
+from core.Thread import Thread
-import logging
-import datetime
-from optparse import OptionParser
class TestON:
'''
-
- TestON will initiate the specified test.
- The main tasks are :
- * Initiate the required Component handles for the test.
+ TestON will initiate the specified test.
+ The main tasks are :
+ * Initiate the required Component handles for the test.
* Create Log file Handles.
-
'''
def __init__(self,options):
'''
Initialise the component handles specified in the topology file of the specified test.
-
'''
# Initialization of the variables.
__builtin__.main = self
-
__builtin__.path = path
__builtin__.utilities = Utilities()
self.TRUE = 1
self.FALSE = 0
self.ERROR = -1
+ self.NORESULT = 2
self.FAIL = False
self.PASS = True
- self.CASERESULT = self.TRUE
+ self.CASERESULT = self.ERROR
+ self.STEPRESULT = self.NORESULT
+ self.stepResults = []
self.init_result = self.TRUE
self.testResult = "Summary"
- self.stepName =""
- self.EXPERIMENTAL_MODE = False
+ self.stepName = ""
+ self.stepCache = ""
+ self.EXPERIMENTAL_MODE = False
self.test_target = None
self.lastcommand = None
- self.testDir = tests_path
- self.configFile = config_path + "teston.cfg"
+ self.testDir = tests_path
+ self.configFile = config_path + "teston.cfg"
self.parsingClass = "xmlparser"
self.parserPath = core_path + "/xmlparser"
self.loggerPath = core_path + "/logger"
self.loggerClass = "Logger"
self.logs_path = logs_path
self.driver = ''
-
-
+ self.Thread = Thread
+
self.configparser()
verifyOptions(options)
load_logger()
@@ -100,18 +99,18 @@
self.driversList=[]
if type(self.componentDictionary) == str :
self.componentDictionary = dict(self.componentDictionary)
-
+
for component in self.componentDictionary :
self.driversList.append(self.componentDictionary[component]['type'])
-
+
self.driversList = list(set(self.driversList)) # Removing duplicates.
# Checking the test_target option set for the component or not
if type(self.componentDictionary) == dict:
for component in self.componentDictionary.keys():
if 'test_target' in self.componentDictionary[component].keys():
self.test_target = component
-
- # Checking for the openspeak file and test script
+
+ # Checking for the openspeak file and test script
self.logger.initlog(self)
# Creating Drivers Handles
@@ -128,7 +127,6 @@
#Ordering components based on the connect order.
ordered_component_list =sorted(components_connect_order, key=lambda key: components_connect_order[key])
print ordered_component_list
-
for component in ordered_component_list:
self.componentInit(component)
@@ -142,28 +140,28 @@
try :
self.configDict = xmldict.xml_to_dict(xml)
return self.configDict
- except :
+ except Exception:
print "There is no such file to parse " + self.configFile
-
+
def componentInit(self,component):
'''
This method will initialize specified component
'''
global driver_options
self.log.info("Creating component Handle: "+component)
- driver_options = {}
+ driver_options = {}
if 'COMPONENTS' in self.componentDictionary[component].keys():
driver_options =dict(self.componentDictionary[component]['COMPONENTS'])
driver_options['name']=component
driverName = self.componentDictionary[component]['type']
driver_options ['type'] = driverName
-
+
classPath = self.getDriverPath(driverName.lower())
- driverModule = __import__(classPath, globals(), locals(), [driverName.lower()], -1)
+ driverModule = importlib.import_module(classPath)
driverClass = getattr(driverModule, driverName)
driverObject = driverClass()
-
+
connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
pwd = self.componentDictionary[component]['password'] if ('password' in self.componentDictionary[component].keys()) else 'changeme',
@@ -171,46 +169,49 @@
options = driver_options)
if not connect_result:
self.log.error("Exiting form the test execution because the connecting to the "+component+" component failed.")
- self.exit()
-
+ self.exit()
+
vars(self)[component] = driverObject
-
+
def run(self):
'''
- The Execution of the test script's cases listed in the Test params file will be done here.
- And Update each test case result.
- This method will return TRUE if it executed all the test cases successfully,
+ The Execution of the test script's cases listed in the Test params file will be done here.
+ And Update each test case result.
+ This method will return TRUE if it executed all the test cases successfully,
else will retun FALSE
'''
-
self.testCaseResult = {}
self.TOTAL_TC = 0
self.TOTAL_TC_RUN = 0
- self.TOTAL_TC_PLANNED = 0
+ self.TOTAL_TC_PLANNED = 0
self.TOTAL_TC_NORESULT = 0
self.TOTAL_TC_FAIL = 0
self.TOTAL_TC_PASS = 0
self.TEST_ITERATION = 0
self.stepCount = 0
- self.CASERESULT = self.TRUE
-
- import testparser
+ self.CASERESULT = self.NORESULT
+
+ import testparser
testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
test = testparser.TestParser(testFile)
self.testscript = test.testscript
self.code = test.getStepCode()
- repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
- main.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
-
+ repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
+ self.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
+
result = self.TRUE
- while(repeat):
+ while(repeat):
for self.CurrentTestCaseNumber in self.testcases_list:
- result = self.runCase(self.CurrentTestCaseNumber)
- repeat-=1
+ result = self.runCase(self.CurrentTestCaseNumber)
+ repeat-=1
return result
-
+
def runCase(self,testCaseNumber):
self.CurrentTestCaseNumber = testCaseNumber
+ self.CurrentTestCase = ""
+ self.stepResults = []
+ self.stepName = ""
+ self.caseExplaination = ""
result = self.TRUE
self.stepCount = 0
self.EXPERIMENTAL_MODE = self.FALSE
@@ -219,34 +220,89 @@
stopped = False
try :
self.stepList = self.code[self.testCaseNumber].keys()
- except KeyError,e:
- main.log.error("There is no Test-Case "+ self.testCaseNumber)
- return main.FALSE
-
+ except KeyError:
+ self.log.error("There is no Test-Case "+ self.testCaseNumber)
+ return self.FALSE
+
self.stepCount = 0
while self.stepCount < len(self.code[self.testCaseNumber].keys()):
result = self.runStep(self.stepList,self.code,self.testCaseNumber)
- if result == main.FALSE:
+ if result == self.FALSE:
break
- elif result == main.TRUE :
+ elif result == self.TRUE:
continue
-
if not stopped :
+ if all( self.TRUE == i for i in self.stepResults ):
+ # ALL PASSED
+ self.CASERESULT = self.TRUE
+ elif self.FALSE in self.stepResults:
+ # AT LEAST ONE FAILED
+ self.CASERESULT = self.FALSE
+ elif self.TRUE in self.stepResults:
+ # AT LEAST ONE PASSED
+ self.CASERESULT = self.TRUE
+ else:
+ self.CASERESULT = self.NORESULT
self.testCaseResult[str(self.CurrentTestCaseNumber)] = self.CASERESULT
self.logger.updateCaseResults(self)
+ self.log.wiki( "<p>" + self.caseExplaination + "</p>" )
+ self.log.summary( self.caseExplaination )
+ self.log.wiki( "<ul>" )
+ for line in self.stepCache.splitlines():
+ if re.search( " - PASS$", line ):
+ self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
+ elif re.search( " - FAIL$", line ):
+ self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
+ elif re.search( " - No Result$", line ):
+ self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
+ self.log.wiki( "</ul>" )
+ self.log.summary( self.stepCache )
+ self.stepCache = ""
return result
-
+
def runStep(self,stepList,code,testCaseNumber):
if not cli.pause:
try :
step = stepList[self.stepCount]
+ self.STEPRESULT = self.NORESULT
exec code[testCaseNumber][step] in module.__dict__
self.stepCount = self.stepCount + 1
+ if step > 0:
+ self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
+ if self.STEPRESULT == self.TRUE:
+ self.stepCache += "PASS\n"
+ #self.stepCache += "PASS <ac:emoticon ac:name=\"tick\" /></li>\n"
+ elif self.STEPRESULT == self.FALSE:
+ self.stepCache += "FAIL\n"
+ #self.stepCache += "FAIL <ac:emoticon ac:name=\"cross\" /></li>\n"
+ else:
+ self.stepCache += "No Result\n"
+ #self.stepCache += "No Result <ac:emoticon ac:name=\"warning\" /></li>\n"
+ self.stepResults.append(self.STEPRESULT)
except TypeError,e:
+ print "\nException in the following section of code: " +\
+ str(testCaseNumber) + "." + str(step) + ": " +\
+ self.stepName
+ #print code[testCaseNumber][step]
self.stepCount = self.stepCount + 1
- self.log.error(e)
+ self.log.exception(e)
+ self.logger.updateCaseResults(self)
+ #WIKI results
+ self.log.wiki( "<ul>" )
+ for line in self.stepCache.splitlines():
+ if re.search( " - PASS$", line ):
+ self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
+ elif re.search( " - FAIL$", line ):
+ self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
+ elif re.search( " - No Result$", line ):
+ self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
+ self.log.wiki( "</ul>" )
+ #summary results
+ self.log.summary( self.stepCache )
+ self.stepCache = ""
+ self.cleanup()
+ self.exit()
return main.TRUE
-
if cli.stop:
cli.stop = False
stopped = True
@@ -255,21 +311,21 @@
self.logger.updateCaseResults(self)
result = self.cleanup()
return main.FALSE
-
+
def addCaseHeader(self):
caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
- self.log.exact(caseHeader)
- caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
+ self.log.exact(caseHeader)
+ caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
for driver in self.componentDictionary.keys():
vars(self)[driver+'log'].info(caseHeader)
-
+
def addCaseFooter(self):
if self.stepCount-1 > 0 :
previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
-
+
caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
-
+
for driver in self.driversList:
vars(self)[driver].write(stepHeader+"\n"+caseFooter)
@@ -282,39 +338,38 @@
'''
result = self.TRUE
self.logger.testSummary(self)
-
+
#self.reportFile.close()
-
#utilities.send_mail()
- try :
- for component in self.componentDictionary.keys():
- tempObject = vars(self)[component]
- print "Disconnecting "+str(tempObject)
-
+ for component in self.componentDictionary.keys():
+ try :
+ tempObject = vars(self)[component]
+ print "Disconnecting from " + str(tempObject.name) + ": " + \
+ str(tempObject)
tempObject.disconnect()
- #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
+ #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
- except(Exception):
- #print " There is an error with closing hanldes"
- result = self.FALSE
+ except (Exception):
+ self.log.exception( "Exception while disconnecting from " +
+ str( component ) )
+ result = self.FALSE
# Closing all the driver's session files
for driver in self.componentDictionary.keys():
vars(self)[driver].close_log_handles()
-
+
return result
-
+
def pause(self):
'''
This function will pause the test's execution, and will continue after user provide 'resume' command.
'''
__builtin__.testthread.pause()
-
+
def onfail(self,*components):
'''
- When test step failed, calling all the components onfail.
+ When test step failed, calling all the components onfail.
'''
-
if not components:
try :
for component in self.componentDictionary.keys():
@@ -323,7 +378,6 @@
except(Exception),e:
print str(e)
result = self.FALSE
-
else:
try :
for component in components:
@@ -332,8 +386,7 @@
except(Exception),e:
print str(e)
result = self.FALSE
-
-
+
def getDriverPath(self,driverName):
'''
Based on the component 'type' specified in the params , this method will find the absolute path ,
@@ -343,23 +396,22 @@
cmd = "find "+drivers_path+" -name "+driverName+".py"
result = commands.getoutput(cmd)
-
+
result_array = str(result).split('\n')
result_count = 0
-
+
for drivers_list in result_array:
result_count = result_count+1
if result_count > 1 :
print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
self.exit()
-
+
result = re.sub("(.*)drivers","",result)
result = re.sub("\.py","",result)
result = re.sub("\.pyc","",result)
result = re.sub("\/",".",result)
result = "drivers"+result
return result
-
def step(self,stepDesc):
'''
@@ -374,34 +426,34 @@
stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
except AttributeError:
stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
-
+
self.log.step(stepName)
stepHeader = ""
if self.stepCount > 1 :
stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
-
- stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
+
+ stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
for driver in self.componentDictionary.keys():
vars(self)[driver+'log'].info(stepHeader)
-
+
def case(self,testCaseName):
'''
Test's each test-case information will append to the logs.
'''
- self.CurrentTestCase = testCaseName
+ self.CurrentTestCase = testCaseName
testCaseName = " " + str(testCaseName) + ""
self.log.case(testCaseName)
- caseHeader = testCaseName+"\n"+"*" * 40+"\n"
+ caseHeader = testCaseName+"\n"+"*" * 40+"\n"
for driver in self.componentDictionary.keys():
vars(self)[driver+'log'].info(caseHeader)
-
+
def testDesc(self,description):
'''
Test description will append to the logs.
'''
description = "Test Description : " + str (description) + ""
self.log.info(description)
-
+
def _getTest(self):
'''
This method will parse the test script to find required test information.
@@ -417,65 +469,57 @@
if lineMatch:
counter = counter + 1
self.TC_PLANNED = len(self.testcases_list)
-
-
+
def response_parser(self,response, return_format):
''' It will load the default response parser '''
response_dict = {}
response_dict = self.response_to_dict(response, return_format)
- return_format_string = self.dict_to_return_format(response,return_format,response_dict)
+ return_format_string = self.dict_to_return_format(response,return_format,response_dict)
return return_format_string
-
+
def response_to_dict(self,response,return_format):
-
response_dict = {}
json_match = re.search('^\s*{', response)
xml_match = re.search('^\s*\<', response)
ini_match = re.search('^\s*\[', response)
if json_match :
- main.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
- # Formatting the json string
-
+ self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
+ # Formatting the json string
response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
response = re.sub(r",\s*'?(\w)", r',"\1', response)
response = re.sub(r"(\w)'?\s*:", r'\1":', response)
response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
-
try :
import json
response_dict = json.loads(response)
- except Exception , e :
- print e
- main.log.error("Json Parser is unable to parse the string")
+ except Exception, e:
+ self.log.exception( e )
+ self.log.error("Json Parser is unable to parse the string")
return response_dict
-
elif ini_match :
- main.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
+ self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
from configobj import ConfigObj
response_file = open("respnse_file.temp",'w')
response_file.write(response)
- response_file.close()
+ response_file.close()
response_dict = ConfigObj("respnse_file.temp")
return response_dict
-
elif xml_match :
- main.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
+ self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
try :
- from core import dicttoobject
response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
except Exception, e:
- main.log.error(e)
+ self.log.exception( e )
return response_dict
-
+
def dict_to_return_format(self,response,return_format,response_dict):
-
if return_format =='table' :
''' Will return in table format'''
to_do = "Call the table output formatter"
global response_table
response_table = '\n'
response_table = response_table +'\t'.join(response_dict)+"\n"
-
+
def get_table(value_to_convert):
''' This will parse the dictionary recusrsively and print as table format'''
table_data = ""
@@ -485,17 +529,13 @@
table_data = table_data + get_table(temp_val)
else :
table_data = table_data + str(value_to_convert) +"\t"
- return table_data
-
+ return table_data
+
for value in response_dict.values() :
response_table = response_table + get_table(value)
-
-
-
- #response_table = response_table + '\t'.join(response_dict.values())
-
+ # response_table = response_table + '\t'.join(response_dict.values())
return response_table
-
+
elif return_format =='config':
''' Will return in config format'''
to_do = 'Call dict to config coverter'
@@ -507,25 +547,22 @@
response_config = re.sub("}", "\n", response_config)
response_config = re.sub(":", " =", response_config)
return "[response]\n\t "+response_config
-
elif return_format == 'xml':
''' Will return in xml format'''
- from core import dicttoobject
response_xml = xmldict.dict_to_xml(response_dict)
response_xml = re.sub(">\s*<", ">\n<", response_xml)
return "\n"+response_xml
-
elif return_format == 'json':
''' Will return in json format'''
to_do = 'Call dict to xml coverter'
import json
response_json = json.dumps(response_dict)
return response_json
-
+
def get_random(self):
self.random_order = self.random_order + 1
return self.random_order
-
+
def exit(self):
__builtin__.testthread = None
sys.exit()
@@ -537,7 +574,7 @@
import pprint
pp = pprint.PrettyPrinter(indent=4)
- #pp.pprint(options)
+ # pp.pprint(options)
verifyTest(options)
verifyExample(options)
verifyTestScript(options)
@@ -564,16 +601,16 @@
main.testDir = path+'/examples/'
main.tests_path = path+"/examples/"
main.classPath = "examples."+main.TEST+"."+main.TEST
-
+
def verifyLogdir(options):
- #Verifying Log directory option
+ # Verifying Log directory option
if options.logdir:
main.logdir = options.logdir
else :
- main.logdir = main.FALSE
-
+ main.logdir = main.FALSE
+
def verifyMail(options):
- # Checking the mailing list
+ # Checking the mailing list
if options.mail:
main.mail = options.mail
elif main.params.has_key('mail'):
@@ -582,10 +619,10 @@
main.mail = 'paxweb@paxterrasolutions.com'
def verifyTestCases(options):
- #Getting Test cases list
+ # Getting Test cases list
if options.testcases:
- testcases_list = options.testcases
- #sys.exit()
+ testcases_list = options.testcases
+ # sys.exit()
testcases_list = re.sub("(\[|\])", "", options.testcases)
main.testcases_list = eval(testcases_list+",")
else :
@@ -593,27 +630,27 @@
temp = eval(main.params['testcases']+",")
list1=[]
if type(temp[0])==list:
- for test in temp:
- for testcase in test:
- if type(testcase)==int:
- testcase=[testcase]
- list1.extend(testcase)
- else :
- temp=list(temp)
- for testcase in temp:
- if type(testcase)==int:
- testcase=[testcase]
- list1.extend(testcase)
- main.testcases_list=list1
+ for test in temp:
+ for testcase in test:
+ if type(testcase)==int:
+ testcase=[testcase]
+ list1.extend(testcase)
+ else :
+ temp=list(temp)
+ for testcase in temp:
+ if type(testcase)==int:
+ testcase=[testcase]
+ list1.extend(testcase)
+ main.testcases_list=list1
else :
print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
- sys.exit()
-
+ sys.exit()
+
def verifyTestScript(options):
'''
Verifyies test script.
'''
- main.openspeak = openspeak.OpenSpeak()
+ main.openspeak = openspeak.OpenSpeak()
openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
if os.path.exists(openspeakfile) :
@@ -624,32 +661,30 @@
print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
__builtin__.testthread = None
main.exit()
-
try :
testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
except(ImportError):
print "There was an import error, it might mean that there is no test like "+main.TEST
- main.exit()
+ main.exit()
testClass = getattr(testModule, main.TEST)
main.testObject = testClass()
load_parser()
- main.params = main.parser.parseParams(main.classPath)
- main.topology = main.parser.parseTopology(main.classPath)
-
+ main.params = main.parser.parseParams(main.classPath)
+ main.topology = main.parser.parseTopology(main.classPath)
+
def verifyParams():
try :
main.params = main.params['PARAMS']
except(KeyError):
print "Error with the params file: Either the file not specified or the format is not correct"
- main.exit()
-
+ main.exit()
try :
main.topology = main.topology['TOPOLOGY']
except(KeyError):
print "Error with the Topology file: Either the file not specified or the format is not correct"
main.exit()
-
+
def load_parser() :
'''
It facilitates the loading customised parser for topology and params file.
@@ -671,19 +706,17 @@
main.parser = parsingClass()
#hashobj = main.parser.parseParams(main.classPath)
if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
-
pass
else:
main.exit()
-
except ImportError:
print sys.exc_info()[1]
main.exit()
else :
print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
- load_defaultParser()
- elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
- load_defaultParser()
+ load_defaultParser()
+ elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
+ load_defaultParser()
else:
load_defaultParser()
@@ -694,7 +727,7 @@
moduleList = main.parserPath.split("/")
newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
try :
- parsingClass = main.parsingClass
+ parsingClass = main.parsingClass
parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
parsingClass = getattr(parsingModule, parsingClass)
main.parser = parsingClass()
@@ -706,7 +739,6 @@
except ImportError:
print sys.exc_info()[1]
-
def load_logger() :
'''
It facilitates the loading customised parser for topology and params file.
@@ -733,8 +765,8 @@
else :
print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
load_defaultlogger()
- elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
- load_defaultlogger()
+ elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
+ load_defaultlogger()
else:
load_defaultlogger()
@@ -745,23 +777,7 @@
moduleList = main.loggerPath.split("/")
newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
try :
- loggerClass = main.loggerClass
- loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
- loggerClass = getattr(loggerModule, loggerClass)
- main.logger = loggerClass()
-
- except ImportError:
- print sys.exc_info()[1]
- main.exit()
-
-def load_defaultlogger():
- '''
- It will load the default parser which is xml parser to parse the params and topology file.
- '''
- moduleList = main.loggerPath.split("/")
- newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
- try :
- loggerClass = main.loggerClass
+ loggerClass = main.loggerClass
loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
loggerClass = getattr(loggerModule, loggerClass)
main.logger = loggerClass()
@@ -770,8 +786,21 @@
print sys.exc_info()[1]
main.exit()
+def load_defaultlogger():
+ '''
+ It will load the default parser which is xml parser to parse the params and topology file.
+ '''
+ moduleList = main.loggerPath.split("/")
+ newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
+ try :
+ loggerClass = main.loggerClass
+ loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
+ loggerClass = getattr(loggerModule, loggerClass)
+ main.logger = loggerClass()
-
+ except ImportError:
+ print sys.exc_info()[1]
+ main.exit()
def _echo(self):
print "THIS IS ECHO"
diff --git a/TestON/core/testparser.py b/TestON/core/testparser.py
index 37f50f0..24b1ca2 100644
--- a/TestON/core/testparser.py
+++ b/TestON/core/testparser.py
@@ -16,7 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with TestON. If not, see <http://www.gnu.org/licenses/>.
+ along with TestON. If not, see <http://www.gnu.org/licenses/>.
'''
@@ -26,21 +26,21 @@
def __init__(self,testFile):
try :
testFileHandler = open(testFile, 'r')
- except IOError:
+ except IOError:
print "No such file "+testFile
sys.exit(0)
-
+
testFileList = testFileHandler.readlines()
- self.testscript = testFileList
+ self.testscript = testFileList
self.caseCode = {}
self.caseBlock = ''
self.statementsList = []
- index = 0
+ index = 0
self.statementsList = []
#initialSpaces = len(line) -len(line.lstrip())
while index < len(testFileList):
testFileList[index] = re.sub("^\s{8}|^\s{4}", "", testFileList[index])
- # Skip multiline comments
+ # Skip multiline comments
if re.match('^(\'\'\')|^(\"\"\")',testFileList[index],0) :
index = index + 1
try :
@@ -48,16 +48,15 @@
index = index + 1
except IndexError,e:
print ''
-
- # skip empty lines and single line comments
+ # skip empty lines and single line comments
elif not re.match('#|^\s*$',testFileList[index],0):
self.statementsList.append(testFileList[index])
index = index + 1
-
+
def case_code(self):
- index = 0
- statementsList = self.statementsList
+ index = 0
+ statementsList = self.statementsList
while index < len(statementsList):
#print statementsList[index]
m= re.match('def\s+CASE(\d+)',statementsList[index],0)
@@ -76,18 +75,16 @@
except IndexError,e:
#print 'IndexError'
print ''
-
self.caseCode [str(m.group(1))] = self.caseBlock
#print "Case CODE "+self.caseCode [str(m.group(1))]
index = index + 1
-
- return self.caseCode
-
+ return self.caseCode
+
def step_code(self,caseStatements):
index = 0
- step = 0
- stepCode = {}
- step_flag = False
+ step = 0
+ stepCode = {}
+ step_flag = False
while index < len(caseStatements):
m= re.match('main\.step',caseStatements[index],0)
stepBlock = ''
@@ -99,13 +96,13 @@
while i < index :
block += caseStatements[i]
i = i + 1
- stepCode[step] = block
+ stepCode[step] = block
step = step + 1
- stepBlock= stepBlock + caseStatements[index]
+ stepBlock = stepBlock + caseStatements[index]
index = index + 1
try :
while not re.match('main\.step',caseStatements[index],0) :
- stepBlock= stepBlock + caseStatements[index]
+ stepBlock = stepBlock + caseStatements[index]
if index < len(caseStatements)-1:
index = index + 1
else :
@@ -121,11 +118,10 @@
if not step_flag :
stepCode[step] = "".join(caseStatements)
return stepCode
-
+
def getStepCode(self):
case_step_code = {}
case_block = self.case_code()
-
for case in case_block :
case_step_code[case] = {}
step_block = self.step_code(case_block[case])
diff --git a/TestON/core/utilities.py b/TestON/core/utilities.py
index b6bed3e..dda43bf 100644
--- a/TestON/core/utilities.py
+++ b/TestON/core/utilities.py
@@ -29,11 +29,9 @@
'''
import re
from configobj import ConfigObj
-import pydoc
from core import ast as ast
import smtplib
-import mimetypes
import email
import os
import email.mime.application
@@ -70,28 +68,22 @@
operators = matchVar.group(2)
elif matchVar.group(1) == "_" and matchVar.group(2):
operators = matchVar.group(2)
-
except AttributeError:
if matchVar==None and nameVar:
operators ='equals'
-
- result = self._assert(NOT=notVar,operator=operators,**kwargs)
+ result = self._assert(NOT=notVar,operator=operators,**kwargs)
if result == main.TRUE:
main.log.info("Assertion Passed")
- main.CASERESULT = main.TRUE
+ main.STEPRESULT = main.TRUE
elif result == main.FALSE:
main.log.warn("Assertion Failed")
- main.CASERESULT = main.FALSE
-
- else :
+ main.STEPRESULT = main.FALSE
+ else:
main.log.error("There is an Error in Assertion")
- main.CASERESULT = main.ERROR
-
+ main.STEPRESULT = main.ERROR
return result
-
return assertHandling
-
-
+
def _assert (self,**assertParam):
'''
It will take the arguments :
@@ -265,7 +257,7 @@
try :
parsedInfo = ConfigObj(self.fileName)
return parsedInfo
- except :
+ except Exception:
print "There is no such file to parse "+fileName
else:
return 0
diff --git a/TestON/core/xmldict.py b/TestON/core/xmldict.py
index 34e9cfc..f873014 100644
--- a/TestON/core/xmldict.py
+++ b/TestON/core/xmldict.py
@@ -37,7 +37,7 @@
root = ElementTree.XML(root_or_str)
try :
return {root.tag: _from_xml(root, strict)}
- except :
+ except Exception:
return None
def dict_to_xml(dict_xml):
diff --git a/TestON/core/xmlparser.py b/TestON/core/xmlparser.py
index 3cb4aee..a46750a 100644
--- a/TestON/core/xmlparser.py
+++ b/TestON/core/xmlparser.py
@@ -39,7 +39,7 @@
try :
parsedInfo = xmldict.xml_to_dict(xml)
return parsedInfo
- except :
+ except Exception:
print "There is no such file to parse " + fileName
else :
print "file name is not correct"