103 __functionDict =
None
109 __extraTestCasesResults =
None
111 __currentResultNode =
None
119 def __init__ (self, testCaseName, isNewlyCreated=False):
142 self.
__xmlRoot.set(
'timeout', infoDict.get(
'timeout',
'0'))
145 etree.SubElement(self.
__xmlRoot,
'Package').text = infoDict[
'package']
146 etree.SubElement(self.
__xmlRoot,
'Author').text = infoDict[
'author']
147 etree.SubElement(self.
__xmlRoot,
'Maintainer').text = infoDict.get(
'maintainer',
'')
148 etree.SubElement(self.
__xmlRoot,
'Comment').text = infoDict.get(
'comment',
'')
149 etree.SubElement(self.
__xmlRoot,
'File').text = infoDict[
'file']
150 etree.SubElement(self.
__xmlRoot,
'Line').text = str(infoDict[
'lineno'])
151 showTestFunctionSortLiterals =
"0"
152 if 'showTestFunctionSortingLiterals' in infoDict:
153 shouldShowLiterals = mevis.MLAB.valueIsTrue(infoDict[
'showTestFunctionSortingLiterals'])
154 showTestFunctionSortLiterals =
"1" if shouldShowLiterals
else "0"
155 etree.SubElement(self.
__xmlRoot,
'showTestFunctionSortingLiterals').text = showTestFunctionSortLiterals
156 if 'preferredRenderer' in infoDict:
157 etree.SubElement(self.
__xmlRoot,
'preferredRenderer').text = infoDict[
'preferredRenderer']
160 if u'dataDirectory' in infoDict:
163 self.
_dataDirectory = os.path.join(os.path.dirname(infoDict[
'file']),
"Data")
165 MLABpriv.clearLogState()
166 MLABpriv.startLogCollect()
168 if not (infoDict
and "scriptFile" in infoDict):
169 mevis.MLAB.logError(f
"Missing scriptFile tag in TestCase {testCaseName}.")
180 etree.SubElement(self.
__xmlRoot,
'Documentation').text = self.
_ctx.scriptVariable(
"__doc__")
183 if MLABpriv.hadLogWarnings()
or MLABpriv.hadLogErrors():
184 self.
__createVirtualTestFunction(
"LoadTestCase", Utils.VIRTUAL_LOAD_TEST_CASE_TEST_FUNCTION,
"Collects errors while the test case is loaded")
189 self.
__createVirtualTestFunction(
"UnloadTestCase", Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION,
"Collects errors while the test case is unloaded")
194 def __createVirtualTestFunction(self, basename, name, documentation):
195 functionsNode = self.
__xmlRoot.find(
"TestFunctions")
196 if functionsNode ==
None:
197 functionsNode = etree.SubElement(self.
__xmlRoot,
"TestFunctions")
198 functionXMLNode = etree.SubElement(functionsNode,
"Function", basename=basename, name=name, is_disabled=str(
False))
199 etree.SubElement(functionXMLNode,
"Documentation").text = documentation
202 return mevis.MLABTestCaseDatabase.testCaseInfo(testCaseName)
253 return self.
_ctx.scriptVariable(funcName)
258 def __callTestFunction (self, funcName):
259 if funcName
in Utils.VIRTUAL_TEST_CASE_FUNCTIONS:
263 raise Exception(
"Unknown function!")
271 if type(callInfo)
in (list, tuple):
272 testFunction, testArguments = callInfo
273 callWithKeywordArguments =
False
274 if len(testArguments) == 1
and isinstance(testArguments[0], dict):
275 signature = inspect.signature(testFunction)
278 signature.bind(**testArguments[0])
279 callWithKeywordArguments =
True
282 if callWithKeywordArguments:
283 result = testFunction(**testArguments[0])
285 result = testFunction(*testArguments)
293 if asyncio.iscoroutine(result):
296 future = asyncio.ensure_future(result)
297 future.add_done_callback(futureDone)
299 QtCore.QCoreApplication.processEvents()
302 if TestSupport.Logging.gStopped:
303 raise CancelTestException
305 except CancelTestException:
308 except TestSupport.Macros.AssertException:
313 mevis.MLAB.logError(f
"Exception occurred in {funcName}:")
318 while self.
_testHelper.getChangeSetStackLength() > changeSetLength:
319 mevis.MLAB.logError(
"You should pop your ChangeSets by yourself!")
325 def __stopCollectingAndStoreAsStartupLog (self):
326 if MLABpriv.hadLogWarnings()
or MLABpriv.hadLogErrors():
334 MLABpriv.stopLogCollect()
343 self.
_ctx.setProperty(
"IsTestCase",
True)
356 if not fieldValueTestCaseSet.load(filename):
357 mevis.MLAB.logError(f
"Failed ot load field-value test ({filename}).")
359 testCase = fieldValueTestCaseSet.get(testcase)
360 testCase.applyParameterization(TestHelper.getInstance().getChangeSet(), verbose=
True)
361 if not testCase.verifyExpectedResults(verbose=
True):
362 mevis.MLAB.logError(
"Failed to verify expected results.")
370 def __createNormalTestNode (self, virtualFunctionName, functionName, functionBaseName, functionDict, isDisabled):
372 if not functionBaseName
in functionDict[
"names"]:
373 xmlNode = self.
__getFunctionInfo(functionBaseName, functionName, isDisabled=isDisabled, sourceName=functionName)
374 functionDict[
"names"].append(functionBaseName)
375 functionDict[
"nodes"][virtualFunctionName] = xmlNode
377 mevis.MLAB.logError(f
"Function with name {functionBaseName} already defined!")
383 return self.
_ctx.call(groupFunctionName, [])
391 def __createTestGroupNode (self, groupFunctionName, orderString, groupName, functionDict, isDisabled):
392 if groupName
in functionDict[
"names"]:
393 mevis.MLAB.logError(f
"A test group with name {groupName} already exists. No duplicate names allowed.")
399 mevis.MLAB.logError(f
"Failed to build virtual functions for the {groupFunctionName} test.")
402 if type(functionList)
not in (list, tuple):
403 mevis.MLAB.logError(f
"The test group function ({groupFunctionName}) must return a list or tuple with function objects!")
406 virtualGroupName = f
"TEST{orderString}_{groupName}"
407 groupXMLNode = etree.Element(
"GroupNode", name=virtualGroupName, basename=groupName, type=
"TestGroup", sourceName=groupFunctionName)
408 etree.SubElement(groupXMLNode,
"Documentation").text = self.
_ctx.scriptVariable(f
"{groupFunctionName}.__doc__")
410 nameToFunctionMap = {}
411 for function
in functionList:
413 if isinstance(function, str):
414 function = self.
_ctx.scriptVariable(function)
415 nameToFunctionMap[function.__name__] = function
417 for functionName
in sorted(nameToFunctionMap.keys()):
418 function = nameToFunctionMap[functionName]
420 functionNodeName = functionName
421 if functionNodeName.startswith(
'DISABLED_'):
422 functionNodeName = functionNodeName[len(
'DISABLED_'):]
424 if functionNodeName
not in functionDict[
"nodes"]
or functionDict[
"nodes"][functionNodeName].tag !=
"Function":
425 mevis.MLAB.logError(f
"Failed to compile function list. Given function {functionNodeName} not a test function "
426 f
"or function already part of a test function group.")
431 virtualFunctionName = (f
"{virtualGroupName}_"
432 f
"{functionNodeName[4:] if not functionNodeName.startswith('DISABLED_') else functionNodeName[13:]}"
435 functionNode = functionDict[
"nodes"][functionNodeName]
436 functionNode.set(
"name", virtualFunctionName)
440 functionNode.set(
"is_disabled", str(isDisabled))
443 del functionDict[
"nodes"][functionNodeName]
449 groupXMLNode.append(functionNode)
451 functionDict[
"names"].append(groupName)
452 functionDict[
"nodes"][virtualGroupName] = groupXMLNode
462 def __createFieldValueTestNode (self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
465 if groupName
in functionDict[
"names"]:
466 mevis.MLAB.logError(f
"A test with name {groupName} already exists. No duplicate names allowed.")
471 retVal = self.
_ctx.call(functionName, [])
474 filename, testCaseList = retVal
if type(retVal)
in (list, tuple)
else (retVal,
None)
476 groupXMLNode = etree.Element(
"GroupNode", name=virtualFunctionBaseName, basename=groupName, type=
"FieldValueTest", sourceName=functionName)
477 etree.SubElement(groupXMLNode,
"Documentation").text = self.
getDocumentation(functionName)
481 functionDict[
"names"].append(groupName)
482 functionDict[
"nodes"][virtualFunctionBaseName] = groupXMLNode
485 if not fvtcs.load(filename):
486 mevis.MLAB.logError(f
"Failed to load the field-value test case set ({filename})!")
490 for testcase
in sorted(fvtcs.getList()):
491 virtualFunctionName = f
"{virtualFunctionBaseName}_{testcase}"
495 availableTestCaseList = fvtcs.getList()
496 for testcase
in sorted(testCaseList):
497 if testcase
in availableTestCaseList:
498 virtualFunctionName = f
"{virtualFunctionBaseName}_{testcase}"
502 mevis.MLAB.logError(f
"The field-value test case {testcase} is unknown!")
511 def __createIterativeTestNode (self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
514 if groupName
in functionDict[
"names"]:
515 mevis.MLAB.logError(f
"A test with name {groupName} already exists. No duplicate names allowed.")
520 retVal = self.
_ctx.call(functionName, [])
524 iterator, function = retVal
526 mevis.MLAB.logError(f
"The iterative test function ({functionName}) must return a list or dictionary"
527 f
" with parameters and a function to call!")
530 groupXMLNode = etree.Element(
"GroupNode", name=virtualFunctionBaseName, basename=groupName, type=
"IterativeTest", sourceName=functionName)
531 etree.SubElement(groupXMLNode,
"Documentation").text = self.
getDocumentation(functionName)
535 functionDict[
"names"].append(groupName)
536 functionDict[
"nodes"][virtualFunctionBaseName] = groupXMLNode
537 regExpFunctionNames = re.compile(
r"^[.\w]+$")
540 if isinstance( iterator, (list, tuple) ):
543 justificationWidth = len(
unicode(len(iterator)-1))
544 for item
in iterator:
546 virtualFunctionId =
unicode(ctr).rjust(justificationWidth,
"0")
547 args = [item]
if (type(item)
not in (list, tuple))
else item
548 virtualFunctionName = f
"{virtualFunctionBaseName}_{virtualFunctionId}"
549 if regExpFunctionNames.match(virtualFunctionName):
550 groupXMLNode.append(self.
__getFunctionInfo(virtualFunctionId, virtualFunctionName, (function, args), isDisabled=isDisabled, sourceName=functionName))
552 mevis.MLAB.logError(f
"The iterative test function ({functionName}) defines non-alphanumeric virtual "
553 f
"function name {virtualFunctionName}!")
555 elif isinstance( iterator, dict ):
556 for item
in sorted(iterator.keys()):
557 args = [iterator[item]]
if (type(iterator[item])
not in (list, tuple))
else iterator[item]
558 virtualFunctionName = f
"{virtualFunctionBaseName}_{item}"
559 if regExpFunctionNames.match(virtualFunctionName):
560 groupXMLNode.append(self.
__getFunctionInfo(
unicode(item), virtualFunctionName, (function, args), isDisabled=isDisabled, sourceName=functionName))
562 mevis.MLAB.logError(f
"The iterative test function ({functionName}) defines non-alphanumeric virtual "
563 f
"function name {virtualFunctionName}!")
565 mevis.MLAB.logError(f
"The iterative test function ({functionName}) must return a list or dictionary with parameters!")
576 def __createUnitTestWrapperNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
580 if groupName
in functionDict[
"names"]:
581 mevis.MLAB.logError(f
"A test with name {groupName} already exists. No duplicate names allowed.")
586 suite = self.
_ctx.call(functionName, [])
589 if not isinstance( suite, unittest.TestSuite ):
590 mevis.MLAB.logError(f
"The unit test wrapper function ({functionName}) must return a unittest.TestSuite!")
593 groupXMLNode = etree.Element(
"GroupNode", name=virtualFunctionBaseName, basename=groupName, type=
"UnitTestWrapper", sourceName=functionName)
594 etree.SubElement(groupXMLNode,
"Documentation").text = self.
getDocumentation(functionName)
598 functionDict[
"names"].append(groupName)
599 functionDict[
"nodes"][virtualFunctionBaseName] = groupXMLNode
601 def _isSkipped(test):
602 isClassSkipped = getattr(test.__class__,
"__unittest_skip__",
False)
603 testMethod = getattr(test, test._testMethodName)
604 isMethodSkipped = getattr(testMethod,
"__unittest_skip__",
False)
605 return isClassSkipped
or isMethodSkipped
608 def _unpackSuite(suite):
610 for test
in suite._tests:
611 if isinstance( test, unittest.TestSuite ):
612 allTests.extend( _unpackSuite( test ) )
614 if not _isSkipped(test):
615 allTests.append( test )
617 allTests = _unpackSuite( suite )
620 testCaseName = test.__class__.__name__
621 testFunctionName = test._testMethodName
622 return '{0}_{1}'.format( testCaseName, testFunctionName )
623 allTests.sort(key=_makeName)
624 testNames = list(map( _makeName, allTests ))
627 def _runUnitTestFunction(testFunction):
638 testFunction.run( testResult )
639 testResult.logResult(
'Test was successful' )
641 for testName, testFunction
in zip( testNames, allTests ):
642 testMethod = getattr(testFunction, testFunction._testMethodName)
643 funcXMLNode = self.
__getFunctionInfo(testName,
'{}_{}'.format(virtualFunctionBaseName, testName),
644 (_runUnitTestFunction, [testFunction]), isDisabled=isDisabled)
645 if hasattr(testMethod,
"__func__"):
646 funcXMLNode.attrib[
"sourceFilename"] = testMethod.__func__.__code__.co_filename
647 funcXMLNode.attrib[
"sourceLine"] = str(testMethod.__func__.__code__.co_firstlineno)
648 elif hasattr(testMethod,
"__code__"):
649 funcXMLNode.attrib[
"sourceFilename"] = testMethod.__code__.co_filename
650 funcXMLNode.attrib[
"sourceLine"] = str(testMethod.__code__.co_firstlineno)
652 funcXMLNode.attrib[
"sourceFilename"] =
""
653 funcXMLNode.attrib[
"sourceLine"] =
"0"
654 groupXMLNode.append(funcXMLNode)
657 return self.
_ctx.callableFunctions()
667 functionInformationDict = {
"names":[],
"nodes":{} }
669 regExpDict = {
"TestFunction": re.compile(
r"^(DISABLED_)?TEST(\d*)_(\w+)$"),
670 "TestGroup": re.compile(
r"^(DISABLED_)?GROUP(\d*)_(\w+)$"),
671 "FieldValueTest": re.compile(
r"^(DISABLED_)?FIELDVALUETEST(\d*)_(\w+)$"),
672 "IterativeTest": re.compile(
r"^(DISABLED_)?ITERATIVETEST(\d*)_(\w+)$"),
673 "UnitTestWrapper": re.compile(
r"^(DISABLED_)?UNITTEST(\d*)_(\w+)$") }
676 functionsNode = etree.SubElement(self.
__xmlRoot,
"TestFunctions")
679 disabledFunctions = self.
_ctx.scriptVariable(
'MLABTC_DISABLED_TEST_FUNCTIONS')
or []
682 functionDict = {
"TestFunction":[],
"TestGroup":[],
"FieldValueTest":[],
"IterativeTest":[],
"UnitTestWrapper":[] }
684 for prefix, functionList
in ((
"TEST", functionDict[
"TestFunction"]),
685 (
"GROUP", functionDict[
"TestGroup"]),
686 (
"FIELDVALUETEST", functionDict[
"FieldValueTest"]),
687 (
"ITERATIVETEST", functionDict[
"IterativeTest"]),
688 (
"UNITTEST", functionDict[
"UnitTestWrapper"]) ):
689 if functionName.startswith(prefix)
or functionName.startswith(
"DISABLED_" + prefix):
690 functionList.append(functionName)
692 for functionName
in sorted(functionDict[
"TestFunction"]):
693 mObj = regExpDict[
"TestFunction"].match(functionName)
695 mevis.MLAB.logError(f
"Name of test function invalid ({functionName})")
697 disabledString, orderString, functionBaseName = mObj.groups()
698 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
699 fname = f
"TEST{orderString}_{functionBaseName}"
700 self.
__createNormalTestNode(fname, functionName, functionBaseName, functionInformationDict, isDisabled=isDisabled)
702 for functionName
in sorted(functionDict[
"TestGroup"]):
703 mObj = regExpDict[
"TestGroup"].match(functionName)
705 mevis.MLAB.logError(f
"Name of test group invalid ({functionName})")
707 disabledString, orderString, groupName = mObj.groups()
708 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
709 self.
__createTestGroupNode(functionName, orderString, groupName, functionInformationDict, isDisabled=isDisabled)
711 for functionName
in sorted(functionDict[
"FieldValueTest"]):
712 mObj = regExpDict[
"FieldValueTest"].match(functionName)
714 mevis.MLAB.logError(f
"Name of field value test invalid ({functionName})")
716 disabledString, orderString, groupName = mObj.groups()
717 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
718 fname = f
"TEST{orderString}_{groupName}"
721 for functionName
in sorted(functionDict[
"IterativeTest"]):
722 mObj = regExpDict[
"IterativeTest"].match(functionName)
724 mevis.MLAB.logError(f
"Name of iterative test invalid ({functionName})")
726 disabledString, orderString, groupName = mObj.groups()
727 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
728 fname = f
"TEST{orderString}_{groupName}"
731 for functionName
in sorted(functionDict[
"UnitTestWrapper"]):
732 mObj = regExpDict[
"UnitTestWrapper"].match(functionName)
734 mevis.MLAB.logError(f
"Name of unit test wrapper invalid ({functionName})")
736 disabledString, orderString, groupName = mObj.groups()
737 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
738 fname = f
"TEST{orderString}_{groupName}"
743 keys = sorted(functionInformationDict[
"nodes"].keys())
745 for functionName
in keys:
746 functionsNode.append(functionInformationDict[
"nodes"][functionName])
747 elif not isNewlyCreated:
748 mevis.MLAB.logError(f
"No test functions found in TestCase {self._testCaseName}!")
756 def __getFunctionInfo (self, functionBaseName, functionName, calledFunction=None, isDisabled=False, sourceName=''):
758 functionXMLNode = etree.Element(
"Function", basename=functionBaseName, name=functionName, sourceName=sourceName, is_disabled=str(isDisabled))
760 etree.SubElement(functionXMLNode,
"Documentation").text = documentation
if documentation
else ""
761 return functionXMLNode
780 return ( self.
_ctx.network().filename() )
787 for fileName
in self.
_ctx.getScriptSourceFiles():
788 mevis.MLAB.priv().openRelatedFile(typeName, fileName)
795 mevis.MLAB.priv().showIDE()
796 self.
_ctx.showInternalNetwork()
826 return self.
__xmlRoot.find(
"Package").text
837 def __callSetUpTestCase (self):
838 if u"setUpTestCase" in self.
_ctx.callableFunctions():
839 self.
_ctx.call(
u"setUpTestCase", [])
844 def __callTearDownTestCase (self):
845 if u"tearDownTestCase" in self.
_ctx.callableFunctions():
846 self.
_ctx.call(
u"tearDownTestCase", [])
849 def __tearDown(self):
851 mevis.MLAB.log(
"Calling tearDown() function...")
859 testResult.logResult(
'')
862 if TestSupport.Logging.gStopped:
863 raise CancelTestException
865 mevis.MLAB.log(
"Destroying test case context...")
871 def run (self, resultNode):
875 TestSupport.Logging.gStopped =
False
882 funcList = resultNode.findall(
'.//Function')
883 length = len(funcList)
890 loadTestCaseFunctionHandled =
False
891 unloadTestCaseFunctionHandled =
False
892 for i
in range(0, length):
893 funcNode = funcList[i]
894 funcName = funcNode.get(
"name")
895 if not loadTestCaseFunctionHandled
and funcName == Utils.VIRTUAL_LOAD_TEST_CASE_TEST_FUNCTION:
897 funcList.insert(0, funcNode)
898 loadTestCaseFunctionHandled =
True
899 elif not unloadTestCaseFunctionHandled
and funcName == Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION:
901 funcList.append(funcNode)
902 unloadTestCaseFunctionHandled =
True
903 if loadTestCaseFunctionHandled
and unloadTestCaseFunctionHandled:
911 for i
in range(0, length):
912 funcNode = funcList[i]
913 funcName = funcNode.get(
"name")
915 isLastTestFunction = i == length-1
925 if not (TestSupport.Logging.gStopOnFirstError
and logHandler.numErrors() > 0):
931 def __prepareRunTestFunction(self, data, availTestFunctions):
933 funcNameForResultDir = data.funcName
935 funcNameForResultDir =
None
936 self.
_testHelper.setTestCaseResultDirectory(self.
getName().replace(
"::", os.sep), funcNameForResultDir)
938 shouldRunTestFunction =
True
941 if data.funcName
not in availTestFunctions
and data.funcName
not in Utils.VIRTUAL_TEST_CASE_FUNCTIONS:
942 mevis.MLAB.logError(f
"Function {data.funcName} does not exist in test case {self.getName()}!")
943 status = Utils.TEST_STATUS_FUNCTION_NOT_FOUND
944 data.funcNode.set(
'status', str(status))
945 shouldRunTestFunction =
False
946 return shouldRunTestFunction
948 def __runTestFunction(self, data):
949 data.started = time.time()
952 data.logHandler.startTestFunction(self.
getType(), self.
getName(), data.funcName)
956 MLABpriv.clearLogState()
963 if data.funcName == Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION:
965 if TestSupport.Logging.gStopped:
966 raise CancelTestException
967 except CancelTestException:
968 data.cancelled =
True
970 def __finishRunTestFunction(self, data):
971 for extraTestCaseResult
in self.
_testHelper.takeExtraTestCaseResults():
975 mevis.MLAB.processEvents()
977 MLABpriv.flushPendingMessages()
979 duration = time.time()-data.started
982 status = Utils.TEST_STATUS_OK
987 data.logHandler.stopTestFunction(status, duration)
992 status = Utils.TEST_STATUS_CANCELLED
993 data.funcNode.set(
'status', str(status))
994 data.funcNode.set(
'duration', str(duration))
995 data.funcNode.append(data.logHandler.getMessages())
997 def __appendCollectedStartupLog(self, logHandler):
1000 msgs = log.split(
'<br>')
1002 mevis.MLAB.log(
"TestCase setup errors/warnings:")
1005 logHandler.appendMessage(msg)
1006 mevis.MLAB.log(
"TestCase execution:")
1009 def __setupTestCaseAndRunTestFunction(self, data):
1010 if data.funcNode.get(
'is_disabled', str(
False)) == str(
False):
1014 if TestSupport.Logging.gStopped:
1015 raise CancelTestException
1016 mevis.MLAB.log(f
"Calling test function {data.funcName}()")
1019 mevis.MLAB.log(f
"Skipping disabled test function {data.funcName}()")
1030 docu = self.
_ctx.scriptVariable(f
"{functionName}.__doc__")
1031 testDocu = docu
if docu
else ""
1032 return re.sub(
r"(?m)^\s+",
"", testDocu)