105 __functionDict =
None
111 __extraTestCasesResults =
None
113 __currentResultNode =
None
121 def __init__(self, testCaseName, isNewlyCreated=False):
144 self.
__xmlRoot.set(
"timeout", infoDict.get(
"timeout",
"0"))
147 etree.SubElement(self.
__xmlRoot,
"Package").text = infoDict[
"package"]
148 etree.SubElement(self.
__xmlRoot,
"Author").text = infoDict[
"author"]
149 etree.SubElement(self.
__xmlRoot,
"Maintainer").text = infoDict.get(
"maintainer",
"")
150 etree.SubElement(self.
__xmlRoot,
"Comment").text = infoDict.get(
"comment",
"")
151 etree.SubElement(self.
__xmlRoot,
"File").text = infoDict[
"file"]
152 etree.SubElement(self.
__xmlRoot,
"Line").text = str(infoDict[
"lineno"])
153 showTestFunctionSortLiterals =
"0"
154 if "showTestFunctionSortingLiterals" in infoDict:
155 shouldShowLiterals = mevis.MLAB.valueIsTrue(infoDict[
"showTestFunctionSortingLiterals"])
156 showTestFunctionSortLiterals =
"1" if shouldShowLiterals
else "0"
157 etree.SubElement(self.
__xmlRoot,
"showTestFunctionSortingLiterals").text = showTestFunctionSortLiterals
158 if "preferredRenderer" in infoDict:
159 etree.SubElement(self.
__xmlRoot,
"preferredRenderer").text = infoDict[
"preferredRenderer"]
162 if "dataDirectory" in infoDict:
165 self.
_dataDirectory = os.path.join(os.path.dirname(infoDict[
"file"]),
"Data")
167 MLABpriv.clearLogState()
168 MLABpriv.startLogCollect()
170 if not (infoDict
and "scriptFile" in infoDict):
171 mevis.MLAB.logError(f
"Missing scriptFile tag in TestCase {testCaseName}.")
182 etree.SubElement(self.
__xmlRoot,
"Documentation").text = self.
_ctx.scriptVariable(
"__doc__")
185 if MLABpriv.hadLogWarnings()
or MLABpriv.hadLogErrors():
188 Utils.VIRTUAL_LOAD_TEST_CASE_TEST_FUNCTION,
189 "Collects errors while the test case is loaded",
197 Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION,
198 "Collects errors while the test case is unloaded",
205 def __createVirtualTestFunction(self, basename, name, documentation):
206 functionsNode = self.
__xmlRoot.find(
"TestFunctions")
207 if functionsNode ==
None:
208 functionsNode = etree.SubElement(self.
__xmlRoot,
"TestFunctions")
209 functionXMLNode = etree.SubElement(
210 functionsNode,
"Function", basename=basename, name=name, is_disabled=str(
False)
212 etree.SubElement(functionXMLNode,
"Documentation").text = documentation
215 return mevis.MLABTestCaseDatabase.testCaseInfo(testCaseName)
268 return self.
_ctx.scriptVariable(funcName)
273 def __callTestFunction(self, funcName):
274 if funcName
in Utils.VIRTUAL_TEST_CASE_FUNCTIONS:
278 raise Exception(
"Unknown function!")
286 if type(callInfo)
in (list, tuple):
287 testFunction, testArguments = callInfo
288 callWithKeywordArguments =
False
289 if len(testArguments) == 1
and isinstance(testArguments[0], dict):
290 signature = inspect.signature(testFunction)
293 signature.bind(**testArguments[0])
294 callWithKeywordArguments =
True
297 if callWithKeywordArguments:
298 result = testFunction(**testArguments[0])
300 result = testFunction(*testArguments)
308 if asyncio.iscoroutine(result):
314 future = asyncio.ensure_future(result)
315 future.add_done_callback(futureDone)
317 QtCore.QCoreApplication.processEvents()
320 if TestSupport.Logging.gStopped:
321 raise CancelTestException
323 except CancelTestException:
326 except TestSupport.Macros.AssertException:
331 mevis.MLAB.logError(f
"Exception occurred in {funcName}:")
336 while self.
_testHelper.getChangeSetStackLength() > changeSetLength:
337 mevis.MLAB.logError(
"You should pop your ChangeSets by yourself!")
344 def __stopCollectingAndStoreAsStartupLog(self):
345 if MLABpriv.hadLogWarnings()
or MLABpriv.hadLogErrors():
353 MLABpriv.stopLogCollect()
362 self.
_ctx.setProperty(
"IsTestCase",
True)
375 if not fieldValueTestCaseSet.load(filename):
376 mevis.MLAB.logError(f
"Failed ot load field-value test ({filename}).")
378 testCase = fieldValueTestCaseSet.get(testcase)
379 testCase.applyParameterization(TestHelper.getInstance().getChangeSet(), verbose=
True)
380 if not testCase.verifyExpectedResults(verbose=
True):
381 mevis.MLAB.logError(
"Failed to verify expected results.")
390 def __createNormalTestNode(self, virtualFunctionName, functionName, functionBaseName, functionDict, isDisabled):
392 if not functionBaseName
in functionDict[
"names"]:
394 functionBaseName, functionName, isDisabled=isDisabled, sourceName=functionName
396 functionDict[
"names"].append(functionBaseName)
397 functionDict[
"nodes"][virtualFunctionName] = xmlNode
399 mevis.MLAB.logError(f
"Function with name {functionBaseName} already defined!")
406 return self.
_ctx.call(groupFunctionName, [])
414 def __createTestGroupNode(self, groupFunctionName, orderString, groupName, functionDict, isDisabled):
415 if groupName
in functionDict[
"names"]:
416 mevis.MLAB.logError(f
"A test group with name {groupName} already exists. No duplicate names allowed.")
422 mevis.MLAB.logError(f
"Failed to build virtual functions for the {groupFunctionName} test.")
425 if type(functionList)
not in (list, tuple):
427 f
"The test group function ({groupFunctionName}) must return a list or tuple with function objects!"
431 virtualGroupName = f
"TEST{orderString}_{groupName}"
432 groupXMLNode = etree.Element(
433 "GroupNode", name=virtualGroupName, basename=groupName, type=
"TestGroup", sourceName=groupFunctionName
435 etree.SubElement(groupXMLNode,
"Documentation").text = self.
_ctx.scriptVariable(f
"{groupFunctionName}.__doc__")
437 nameToFunctionMap = {}
438 for function
in functionList:
440 if isinstance(function, str):
441 function = self.
_ctx.scriptVariable(function)
442 nameToFunctionMap[function.__name__] = function
444 for functionName
in sorted(nameToFunctionMap.keys()):
445 function = nameToFunctionMap[functionName]
447 functionNodeName = functionName
448 if functionNodeName.startswith(
"DISABLED_"):
449 functionNodeName = functionNodeName[len(
"DISABLED_") :]
452 functionNodeName
not in functionDict[
"nodes"]
453 or functionDict[
"nodes"][functionNodeName].tag !=
"Function"
456 f
"Failed to compile function list. Given function {functionNodeName} not a test function "
457 f
"or function already part of a test function group."
463 virtualFunctionName = (
464 f
"{virtualGroupName}_"
465 f
"{functionNodeName[4:] if not functionNodeName.startswith('DISABLED_') else functionNodeName[13:]}"
468 functionNode = functionDict[
"nodes"][functionNodeName]
469 functionNode.set(
"name", virtualFunctionName)
473 functionNode.set(
"is_disabled", str(isDisabled))
476 del functionDict[
"nodes"][functionNodeName]
482 groupXMLNode.append(functionNode)
484 functionDict[
"names"].append(groupName)
485 functionDict[
"nodes"][virtualGroupName] = groupXMLNode
496 def __createFieldValueTestNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
499 if groupName
in functionDict[
"names"]:
500 mevis.MLAB.logError(f
"A test with name {groupName} already exists. No duplicate names allowed.")
505 retVal = self.
_ctx.call(functionName, [])
508 filename, testCaseList = retVal
if type(retVal)
in (list, tuple)
else (retVal,
None)
510 groupXMLNode = etree.Element(
512 name=virtualFunctionBaseName,
514 type=
"FieldValueTest",
515 sourceName=functionName,
517 etree.SubElement(groupXMLNode,
"Documentation").text = self.
getDocumentation(functionName)
521 functionDict[
"names"].append(groupName)
522 functionDict[
"nodes"][virtualFunctionBaseName] = groupXMLNode
525 if not fvtcs.load(filename):
526 mevis.MLAB.logError(f
"Failed to load the field-value test case set ({filename})!")
530 for testcase
in sorted(fvtcs.getList()):
531 virtualFunctionName = f
"{virtualFunctionBaseName}_{testcase}"
537 isDisabled=isDisabled,
538 sourceName=functionName,
542 availableTestCaseList = fvtcs.getList()
543 for testcase
in sorted(testCaseList):
544 if testcase
in availableTestCaseList:
545 virtualFunctionName = f
"{virtualFunctionBaseName}_{testcase}"
551 isDisabled=isDisabled,
552 sourceName=functionName,
556 mevis.MLAB.logError(f
"The field-value test case {testcase} is unknown!")
566 def __createIterativeTestNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
569 if groupName
in functionDict[
"names"]:
570 mevis.MLAB.logError(f
"A test with name {groupName} already exists. No duplicate names allowed.")
575 retVal = self.
_ctx.call(functionName, [])
579 iterator, function = retVal
582 f
"The iterative test function ({functionName}) must return a list or dictionary"
583 f
" with parameters and a function to call!"
587 groupXMLNode = etree.Element(
588 "GroupNode", name=virtualFunctionBaseName, basename=groupName, type=
"IterativeTest", sourceName=functionName
590 etree.SubElement(groupXMLNode,
"Documentation").text = self.
getDocumentation(functionName)
594 functionDict[
"names"].append(groupName)
595 functionDict[
"nodes"][virtualFunctionBaseName] = groupXMLNode
596 regExpFunctionNames = re.compile(
r"^[.\w]+$")
599 if isinstance(iterator, (list, tuple)):
602 justificationWidth = len(
unicode(len(iterator) - 1))
603 for item
in iterator:
605 virtualFunctionId =
unicode(ctr).rjust(justificationWidth,
"0")
606 args = [item]
if (type(item)
not in (list, tuple))
else item
607 virtualFunctionName = f
"{virtualFunctionBaseName}_{virtualFunctionId}"
608 if regExpFunctionNames.match(virtualFunctionName):
614 isDisabled=isDisabled,
615 sourceName=functionName,
620 f
"The iterative test function ({functionName}) defines non-alphanumeric virtual "
621 f
"function name {virtualFunctionName}!"
624 elif isinstance(iterator, dict):
625 for item
in sorted(iterator.keys()):
626 args = [iterator[item]]
if (type(iterator[item])
not in (list, tuple))
else iterator[item]
627 virtualFunctionName = f
"{virtualFunctionBaseName}_{item}"
628 if regExpFunctionNames.match(virtualFunctionName):
634 isDisabled=isDisabled,
635 sourceName=functionName,
640 f
"The iterative test function ({functionName}) defines non-alphanumeric virtual "
641 f
"function name {virtualFunctionName}!"
645 f
"The iterative test function ({functionName}) must return a list or dictionary with parameters!"
657 def __createUnitTestWrapperNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
661 if groupName
in functionDict[
"names"]:
662 mevis.MLAB.logError(f
"A test with name {groupName} already exists. No duplicate names allowed.")
667 suite = self.
_ctx.call(functionName, [])
670 if not isinstance(suite, unittest.TestSuite):
671 mevis.MLAB.logError(f
"The unit test wrapper function ({functionName}) must return a unittest.TestSuite!")
674 groupXMLNode = etree.Element(
676 name=virtualFunctionBaseName,
678 type=
"UnitTestWrapper",
679 sourceName=functionName,
681 etree.SubElement(groupXMLNode,
"Documentation").text = self.
getDocumentation(functionName)
685 functionDict[
"names"].append(groupName)
686 functionDict[
"nodes"][virtualFunctionBaseName] = groupXMLNode
688 def _isSkipped(test):
689 isClassSkipped = getattr(test.__class__,
"__unittest_skip__",
False)
690 testMethod = getattr(test, test._testMethodName)
691 isMethodSkipped = getattr(testMethod,
"__unittest_skip__",
False)
692 return isClassSkipped
or isMethodSkipped
695 def _unpackSuite(suite):
697 for test
in suite._tests:
698 if isinstance(test, unittest.TestSuite):
699 allTests.extend(_unpackSuite(test))
701 if not _isSkipped(test):
702 allTests.append(test)
705 allTests = _unpackSuite(suite)
708 testCaseName = test.__class__.__name__
709 testFunctionName = test._testMethodName
710 return "{0}_{1}".format(testCaseName, testFunctionName)
712 allTests.sort(key=_makeName)
713 testNames = list(map(_makeName, allTests))
716 def _runUnitTestFunction(testFunction):
727 testFunction.run(testResult)
728 testResult.logResult(
"Test was successful")
730 for testName, testFunction
in zip(testNames, allTests):
731 testMethod = getattr(testFunction, testFunction._testMethodName)
734 "{}_{}".format(virtualFunctionBaseName, testName),
735 (_runUnitTestFunction, [testFunction]),
736 isDisabled=isDisabled,
738 if hasattr(testMethod,
"__func__"):
739 funcXMLNode.attrib[
"sourceFilename"] = testMethod.__func__.__code__.co_filename
740 funcXMLNode.attrib[
"sourceLine"] = str(testMethod.__func__.__code__.co_firstlineno)
741 elif hasattr(testMethod,
"__code__"):
742 funcXMLNode.attrib[
"sourceFilename"] = testMethod.__code__.co_filename
743 funcXMLNode.attrib[
"sourceLine"] = str(testMethod.__code__.co_firstlineno)
745 funcXMLNode.attrib[
"sourceFilename"] =
""
746 funcXMLNode.attrib[
"sourceLine"] =
"0"
747 groupXMLNode.append(funcXMLNode)
750 return self.
_ctx.callableFunctions()
760 functionInformationDict = {
"names": [],
"nodes": {}}
763 "TestFunction": re.compile(
r"^(DISABLED_)?TEST(\d*)_(\w+)$"),
764 "TestGroup": re.compile(
r"^(DISABLED_)?GROUP(\d*)_(\w+)$"),
765 "FieldValueTest": re.compile(
r"^(DISABLED_)?FIELDVALUETEST(\d*)_(\w+)$"),
766 "IterativeTest": re.compile(
r"^(DISABLED_)?ITERATIVETEST(\d*)_(\w+)$"),
767 "UnitTestWrapper": re.compile(
r"^(DISABLED_)?UNITTEST(\d*)_(\w+)$"),
771 functionsNode = etree.SubElement(self.
__xmlRoot,
"TestFunctions")
774 disabledFunctions = self.
_ctx.scriptVariable(
"MLABTC_DISABLED_TEST_FUNCTIONS")
or []
780 "FieldValueTest": [],
782 "UnitTestWrapper": [],
785 for prefix, functionList
in (
786 (
"TEST", functionDict[
"TestFunction"]),
787 (
"GROUP", functionDict[
"TestGroup"]),
788 (
"FIELDVALUETEST", functionDict[
"FieldValueTest"]),
789 (
"ITERATIVETEST", functionDict[
"IterativeTest"]),
790 (
"UNITTEST", functionDict[
"UnitTestWrapper"]),
792 if functionName.startswith(prefix)
or functionName.startswith(
"DISABLED_" + prefix):
793 functionList.append(functionName)
795 for functionName
in sorted(functionDict[
"TestFunction"]):
796 mObj = regExpDict[
"TestFunction"].match(functionName)
798 mevis.MLAB.logError(f
"Name of test function invalid ({functionName})")
800 disabledString, orderString, functionBaseName = mObj.groups()
801 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
802 fname = f
"TEST{orderString}_{functionBaseName}"
804 fname, functionName, functionBaseName, functionInformationDict, isDisabled=isDisabled
807 for functionName
in sorted(functionDict[
"TestGroup"]):
808 mObj = regExpDict[
"TestGroup"].match(functionName)
810 mevis.MLAB.logError(f
"Name of test group invalid ({functionName})")
812 disabledString, orderString, groupName = mObj.groups()
813 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
815 functionName, orderString, groupName, functionInformationDict, isDisabled=isDisabled
818 for functionName
in sorted(functionDict[
"FieldValueTest"]):
819 mObj = regExpDict[
"FieldValueTest"].match(functionName)
821 mevis.MLAB.logError(f
"Name of field value test invalid ({functionName})")
823 disabledString, orderString, groupName = mObj.groups()
824 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
825 fname = f
"TEST{orderString}_{groupName}"
827 fname, functionName, groupName, functionInformationDict, isDisabled=isDisabled
830 for functionName
in sorted(functionDict[
"IterativeTest"]):
831 mObj = regExpDict[
"IterativeTest"].match(functionName)
833 mevis.MLAB.logError(f
"Name of iterative test invalid ({functionName})")
835 disabledString, orderString, groupName = mObj.groups()
836 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
837 fname = f
"TEST{orderString}_{groupName}"
839 fname, functionName, groupName, functionInformationDict, isDisabled=isDisabled
842 for functionName
in sorted(functionDict[
"UnitTestWrapper"]):
843 mObj = regExpDict[
"UnitTestWrapper"].match(functionName)
845 mevis.MLAB.logError(f
"Name of unit test wrapper invalid ({functionName})")
847 disabledString, orderString, groupName = mObj.groups()
848 isDisabled = (disabledString
is not None)
or (functionName
in disabledFunctions)
849 fname = f
"TEST{orderString}_{groupName}"
851 fname, functionName, groupName, functionInformationDict, isDisabled=isDisabled
856 keys = sorted(functionInformationDict[
"nodes"].keys())
858 for functionName
in keys:
859 functionsNode.append(functionInformationDict[
"nodes"][functionName])
860 elif not isNewlyCreated:
861 mevis.MLAB.logError(f
"No test functions found in TestCase {self._testCaseName}!")
870 def __getFunctionInfo(self, functionBaseName, functionName, calledFunction=None, isDisabled=False, sourceName=""):
872 functionXMLNode = etree.Element(
873 "Function", basename=functionBaseName, name=functionName, sourceName=sourceName, is_disabled=str(isDisabled)
876 etree.SubElement(functionXMLNode,
"Documentation").text = documentation
if documentation
else ""
877 return functionXMLNode
899 return self.
_ctx.network().filename()
907 for fileName
in self.
_ctx.getScriptSourceFiles():
908 mevis.MLAB.priv().openRelatedFile(typeName, fileName)
916 mevis.MLAB.priv().showIDE()
917 self.
_ctx.showInternalNetwork()
952 return self.
__xmlRoot.find(
"Package").text
965 def __callSetUpTestCase(self):
966 if "setUpTestCase" in self.
_ctx.callableFunctions():
967 self.
_ctx.call(
"setUpTestCase", [])
973 def __callTearDownTestCase(self):
974 if "tearDownTestCase" in self.
_ctx.callableFunctions():
975 self.
_ctx.call(
"tearDownTestCase", [])
979 def __tearDown(self):
981 mevis.MLAB.log(
"Calling tearDown() function...")
989 testResult.logResult(
"")
992 if TestSupport.Logging.gStopped:
993 raise CancelTestException
995 mevis.MLAB.log(
"Destroying test case context...")
1005 TestSupport.Logging.gStopped =
False
1012 funcList = resultNode.findall(
".//Function")
1013 length = len(funcList)
1020 loadTestCaseFunctionHandled =
False
1021 unloadTestCaseFunctionHandled =
False
1022 for i
in range(0, length):
1023 funcNode = funcList[i]
1024 funcName = funcNode.get(
"name")
1025 if not loadTestCaseFunctionHandled
and funcName == Utils.VIRTUAL_LOAD_TEST_CASE_TEST_FUNCTION:
1027 funcList.insert(0, funcNode)
1028 loadTestCaseFunctionHandled =
True
1029 elif not unloadTestCaseFunctionHandled
and funcName == Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION:
1031 funcList.append(funcNode)
1032 unloadTestCaseFunctionHandled =
True
1033 if loadTestCaseFunctionHandled
and unloadTestCaseFunctionHandled:
1041 for i
in range(0, length):
1042 funcNode = funcList[i]
1043 funcName = funcNode.get(
"name")
1045 isLastTestFunction = i == length - 1
1055 if not (TestSupport.Logging.gStopOnFirstError
and logHandler.numErrors() > 0):
1061 def __prepareRunTestFunction(self, data, availTestFunctions):
1063 funcNameForResultDir = data.funcName
1065 funcNameForResultDir =
None
1066 self.
_testHelper.setTestCaseResultDirectory(self.
getName().replace(
"::", os.sep), funcNameForResultDir)
1068 shouldRunTestFunction =
True
1071 if data.funcName
not in availTestFunctions
and data.funcName
not in Utils.VIRTUAL_TEST_CASE_FUNCTIONS:
1072 mevis.MLAB.logError(f
"Function {data.funcName} does not exist in test case {self.getName()}!")
1073 status = Utils.TEST_STATUS_FUNCTION_NOT_FOUND
1074 data.funcNode.set(
"status", str(status))
1075 shouldRunTestFunction =
False
1076 return shouldRunTestFunction
1078 def __runTestFunction(self, data):
1079 data.started = time.time()
1082 data.logHandler.startTestFunction(self.
getType(), self.
getName(), data.funcName)
1086 MLABpriv.clearLogState()
1093 if data.funcName == Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION:
1095 if TestSupport.Logging.gStopped:
1096 raise CancelTestException
1097 except CancelTestException:
1098 data.cancelled =
True
1100 def __finishRunTestFunction(self, data):
1101 for extraTestCaseResult
in self.
_testHelper.takeExtraTestCaseResults():
1105 mevis.MLAB.processEvents()
1107 MLABpriv.flushPendingMessages()
1109 duration = time.time() - data.started
1112 status = Utils.TEST_STATUS_OK
1114 status = Utils.TEST_STATUS_WARNING
1116 status = Utils.TEST_STATUS_ERROR
1119 data.logHandler.stopTestFunction(status, duration)
1124 status = Utils.TEST_STATUS_CANCELLED
1125 data.funcNode.set(
"status", str(status))
1126 data.funcNode.set(
"duration", str(duration))
1127 data.funcNode.append(data.logHandler.getMessages())
1129 def __appendCollectedStartupLog(self, logHandler):
1132 msgs = log.split(
"<br>")
1134 mevis.MLAB.log(
"TestCase setup errors/warnings:")
1137 logHandler.appendMessage(msg)
1138 mevis.MLAB.log(
"TestCase execution:")
1141 def __setupTestCaseAndRunTestFunction(self, data):
1142 if data.funcNode.get(
"is_disabled", str(
False)) == str(
False):
1146 if TestSupport.Logging.gStopped:
1147 raise CancelTestException
1148 mevis.MLAB.log(f
"Calling test function {data.funcName}()")
1151 mevis.MLAB.log(f
"Skipping disabled test function {data.funcName}()")
1162 docu = self.
_ctx.scriptVariable(f
"{functionName}.__doc__")
1163 testDocu = docu
if docu
else ""
1164 return re.sub(
r"(?m)^\s+",
"", testDocu)