TestCenter Reference
TestCase.py
Go to the documentation of this file.
1 #
2 # Copyright 2009, MeVis Medical Solutions AG
3 #
4 # The user may use this file in accordance with the license agreement provided with
5 # the Software or, alternatively, in accordance with the terms contained in a
6 # written agreement between the user and MeVis Medical Solutions AG.
7 #
8 # For further information use the contact form at https://www.mevislab.de/contact
9 #
10 
11 
13 
14 # -- system imports ----------------------------------------------------------------------------{{{-
15 import inspect
16 import os
17 import re
18 import sys
19 import time
20 import traceback
21 import unittest
22 import asyncio
23 from PythonQt import QtCore
24 
25 if sys.version_info.major >= 3:
26  unicode = str
27 
28 import xml.etree.cElementTree as etree
29 
30 # ----------------------------------------------------------------------------------------------}}}-
31 
32 # -- local imports -----------------------------------------------------------------------------{{{-
33 import mevis
34 from TestSupport.FieldValueTests import FieldValueTestCaseSet
35 
36 from TestSupport.TestHelper import TestHelper, CancelTestException
37 from . import Utils
39 import TestSupport.Macros
40 
41 # ----------------------------------------------------------------------------------------------}}}-
42 
43 # -- local imports -----------------------------------------------------------------------------{{{-
44 MLABpriv = mevis.MLAB.priv()
45 # ----------------------------------------------------------------------------------------------}}}-
46 
47 
48 # Prints the exception that occurred during a test function.
50  exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
51  tb = exceptionTraceback.tb_next
52  traceback.print_tb(tb, limit=None, file=sys.stderr)
53  lines = traceback.format_exception_only(exceptionType, exceptionValue)
54  for line in lines:
55  sys.stderr.write(line)
56 
57 
59  def __init__(self, funcNode, funcName, logHandler, isLastTestFunction):
60  self.funcNodefuncNode = funcNode
61  self.funcNamefuncName = funcName
62  self.logHandlerlogHandler = logHandler
63  self.isLastTestFunctionisLastTestFunction = isLastTestFunction
64  self.startedstarted = None
65  self.cancelledcancelled = False
66 
67 
68 class UnitTestResult(unittest.TestResult):
69 
70  # deactivate stdout/stderr redirection, the output is captured by the TestCenter anyway
71  def _setupStdout(self):
72  pass
73 
74  def _restoreStdout(self):
75  pass
76 
77  def logResult(self, successMsg):
78  if self.wasSuccessful() and successMsg:
79  mevis.MLAB.log(successMsg)
80  if self.errors:
81  for error in self.errors:
82  mevis.MLAB.logError(error[1])
83  if self.failures:
84  for failure in self.failures:
85  mevis.MLAB.logError(failure[1])
86 
87 
88 # -- class TestCase ----------------------------------------------------------------------------{{{-
89 
90 class TestCase:
91  # -- member variables ------------------------------------------------------------------------{{{-
92 
93  _ctx = None
94 
95  _testHelper = None
96 
97 
98  _testCaseName = None
99 
100  _testCaseType = None
101 
102 
103  __xmlRoot = None
104 
105  __functionDict = None
106 
107 
108  __valid = None
109 
110  # XML node for extra test case results
111  __extraTestCasesResults = None
112 
113  __currentResultNode = None
114  # --------------------------------------------------------------------------------------------}}}-
115 
116  # -- def __init__ ----------------------------------------------------------------------------{{{-
117 
121  def __init__(self, testCaseName, isNewlyCreated=False):
122  self._testCaseName_testCaseName = testCaseName
123  self._testHelper_testHelper = TestHelper.getInstance()
124  self.__testCaseListener__testCaseListener = None
125 
126  self.__collectedStartupLog__collectedStartupLog = None
127  self.__collectedStartupErrorsState__collectedStartupErrorsState = False
128  self.__collectedStartupWarningsState__collectedStartupWarningsState = False
129  self.__setupTestCaseCalled__setupTestCaseCalled = False
130 
131  self.__valid__valid = False
132  self.__functionDict__functionDict = {}
133 
134 
135  self.__dummyTestSuite__dummyTestSuite = None
136 
137 
138  self.__previousTestClass__previousTestClass = None
139 
140  infoDict = self._getTestCaseInfo_getTestCaseInfo(testCaseName)
141 
142  # Get the basic test case information and store them in the XML node.
143  self.__xmlRoot__xmlRoot = etree.Element("TestCase", name=self._testCaseName_testCaseName, type=self._testCaseType_testCaseType)
144  self.__xmlRoot__xmlRoot.set("timeout", infoDict.get("timeout", "0"))
145  self.__perFunctionResultDirectory__perFunctionResultDirectory = mevis.MLAB.valueIsTrue(infoDict.get("perFunctionResultDirectory", "1"))
146 
147  etree.SubElement(self.__xmlRoot__xmlRoot, "Package").text = infoDict["package"]
148  etree.SubElement(self.__xmlRoot__xmlRoot, "Author").text = infoDict["author"]
149  etree.SubElement(self.__xmlRoot__xmlRoot, "Maintainer").text = infoDict.get("maintainer", "")
150  etree.SubElement(self.__xmlRoot__xmlRoot, "Comment").text = infoDict.get("comment", "")
151  etree.SubElement(self.__xmlRoot__xmlRoot, "File").text = infoDict["file"]
152  etree.SubElement(self.__xmlRoot__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__xmlRoot, "showTestFunctionSortingLiterals").text = showTestFunctionSortLiterals
158  if "preferredRenderer" in infoDict:
159  etree.SubElement(self.__xmlRoot__xmlRoot, "preferredRenderer").text = infoDict["preferredRenderer"]
160 
161  # Set the data directory. If not specified use default value.
162  if "dataDirectory" in infoDict:
163  self._dataDirectory_dataDirectory = infoDict["dataDirectory"]
164  else:
165  self._dataDirectory_dataDirectory = os.path.join(os.path.dirname(infoDict["file"]), "Data")
166 
167  MLABpriv.clearLogState()
168  MLABpriv.startLogCollect()
169 
170  if not (infoDict and "scriptFile" in infoDict):
171  mevis.MLAB.logError(f"Missing scriptFile tag in TestCase {testCaseName}.")
172  else:
173  self._loadScriptFile_loadScriptFile(infoDict["scriptFile"])
174  # we need to activate the TestCase, because building of the virtual functions will call into
175  # TestHelper functions...
176  self.activateactivate()
177 
178  self._buildVirtualFunctions_buildVirtualFunctions(isNewlyCreated)
179 
180  self.deactivatedeactivate()
181 
182  etree.SubElement(self.__xmlRoot__xmlRoot, "Documentation").text = self._ctx_ctx.scriptVariable("__doc__")
183 
184  # create a virtual test function to show the setup errors
185  if MLABpriv.hadLogWarnings() or MLABpriv.hadLogErrors():
186  self.__createVirtualTestFunction__createVirtualTestFunction(
187  "LoadTestCase",
188  Utils.VIRTUAL_LOAD_TEST_CASE_TEST_FUNCTION,
189  "Collects errors while the test case is loaded",
190  )
191  else:
192  self.__valid__valid = True
193 
194  # create a virtual test function to show tear down errors
195  self.__createVirtualTestFunction__createVirtualTestFunction(
196  "UnloadTestCase",
197  Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION,
198  "Collects errors while the test case is unloaded",
199  )
200 
201  self.__stopCollectingAndStoreAsStartupLog__stopCollectingAndStoreAsStartupLog()
202 
203  # --------------------------------------------------------------------------------------------}}}-
204 
205  def __createVirtualTestFunction(self, basename, name, documentation):
206  functionsNode = self.__xmlRoot__xmlRoot.find("TestFunctions")
207  if functionsNode == None:
208  functionsNode = etree.SubElement(self.__xmlRoot__xmlRoot, "TestFunctions")
209  functionXMLNode = etree.SubElement(
210  functionsNode, "Function", basename=basename, name=name, is_disabled=str(False)
211  )
212  etree.SubElement(functionXMLNode, "Documentation").text = documentation
213 
214  def _getTestCaseInfo(self, testCaseName):
215  return mevis.MLABTestCaseDatabase.testCaseInfo(testCaseName)
216 
217  # -- def __del__ -----------------------------------------------------------------------------{{{-
218 
219  def __del__(self):
220  self.destroyContextdestroyContext()
221 
222  # --------------------------------------------------------------------------------------------}}}-
223 
224  def destroyContext(self):
225  if self._ctx_ctx:
226  try:
227  self._ctx_ctx.remove()
228  finally:
229  self._ctx_ctx = None
230 
231  def activate(self):
232  # Tell the TestHelper about us, but don't set a reference
233  # to self to the TestHelper to avoid that it reference counts us:
234  self._testHelper_testHelper.setMacrosLogOnSuccess(True)
235  self._testHelper_testHelper.setTestCaseContext(self._ctx_ctx)
236  self._testHelper_testHelper.setTestCaseName(self._testCaseName_testCaseName)
237  self._testHelper_testHelper.setTestCaseDataDirectory(self._dataDirectory_dataDirectory)
238  self._testHelper_testHelper.pushChangeSet()
239 
240  # --------------------------------------------------------------------------------------------}}}-
241 
242  def deactivate(self):
243  # Reset the test helper. If activate()/deactivate() should need to be
244  # called recursive in the the future, we would need to keep a stack here and in
245  # activate().
246  self._testHelper_testHelper.setTestCaseContext(None)
247  self._testHelper_testHelper.setTestCaseName("")
248  self._testHelper_testHelper.setTestCaseDataDirectory("")
249  self._testHelper_testHelper.popChangeSet()
250  self._testHelper_testHelper.setMacrosLogOnSuccess(True)
251 
252  # --------------------------------------------------------------------------------------------}}}-
253 
254  def setTestCaseListener(self, testCaseListener):
255  self.__testCaseListener__testCaseListener = testCaseListener
256 
257  # -- def addExtraTestCaseResult ------------------------------------------------------------------{{{-
258  def addExtraTestCaseResult(self, extraTestCaseResult):
259  assert self.__currentResultNode__currentResultNode != None
260  assert self.__currentResultNode__currentResultNode != self.__xmlRoot__xmlRoot
261  if self.__extraTestCasesResults__extraTestCasesResults == None:
262  self.__extraTestCasesResults__extraTestCasesResults = etree.SubElement(self.__currentResultNode__currentResultNode, "ExtraTestCasesResults")
263  self.__extraTestCasesResults__extraTestCasesResults.append(extraTestCaseResult.toXML())
264 
265  # --------------------------------------------------------------------------------------------}}}-
266 
267  def _getTestFunction(self, funcName):
268  return self._ctx_ctx.scriptVariable(funcName)
269 
270  # -- def __callTestFunction ------------------------------------------------------------------{{{-
271 
273  def __callTestFunction(self, funcName):
274  if funcName in Utils.VIRTUAL_TEST_CASE_FUNCTIONS:
275  return
276 
277  if not funcName in self.__functionDict__functionDict:
278  raise Exception("Unknown function!")
279 
280  changeSetLength = self._testHelper_testHelper.pushChangeSet()
281 
282  callInfo = self.__functionDict__functionDict[funcName]
283 
284  try:
285  if callInfo:
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)
291  try:
292  # try to bind the test arguments as keyword arguments to the test function
293  signature.bind(**testArguments[0])
294  callWithKeywordArguments = True
295  except TypeError:
296  pass
297  if callWithKeywordArguments:
298  result = testFunction(**testArguments[0])
299  else:
300  result = testFunction(*testArguments)
301  else:
302  result = self._getTestFunction_getTestFunction(callInfo)()
303  else:
304  result = self._getTestFunction_getTestFunction(funcName)()
305 
306  # if the result is a coroutine, we schedule it and process events until it
307  # has finished... This allows test functions to use the async keyword.
308  if asyncio.iscoroutine(result):
309  self.futureDonefutureDone = False
310 
311  def futureDone(*args):
312  self.futureDonefutureDone = True
313 
314  future = asyncio.ensure_future(result)
315  future.add_done_callback(futureDone)
316  while not self.futureDonefutureDone:
317  QtCore.QCoreApplication.processEvents()
318  future.result()
319 
320  if TestSupport.Logging.gStopped:
321  raise CancelTestException
322 
323  except CancelTestException:
324  self._testHelper_testHelper.clearChangeSet()
325  raise
326  except TestSupport.Macros.AssertException:
327  # an assertion has failed and we should stop execution,
328  # but this is an expected exception, so we don't print it.
329  pass
330  except: # pylint: disable=W0702
331  mevis.MLAB.logError(f"Exception occurred in {funcName}:")
333 
334  # Clean up the environment.
335  self._testHelper_testHelper.popChangeSet()
336  while self._testHelper_testHelper.getChangeSetStackLength() > changeSetLength:
337  mevis.MLAB.logError("You should pop your ChangeSets by yourself!")
338  self._testHelper_testHelper.popChangeSet()
339 
340  # --------------------------------------------------------------------------------------------}}}-
341 
342  # -- def __stopCollectingAndStoreAsStartupLog ------------------------------------------------------------------------------{{{-
343 
344  def __stopCollectingAndStoreAsStartupLog(self):
345  if MLABpriv.hadLogWarnings() or MLABpriv.hadLogErrors():
346  self.__collectedStartupLog__collectedStartupLog = MLABpriv.collectedLog()
347  self.__collectedStartupErrorsState__collectedStartupErrorsState = MLABpriv.hadLogErrors()
348  self.__collectedStartupWarningsState__collectedStartupWarningsState = MLABpriv.hadLogWarnings()
349  else:
350  self.__collectedStartupLog__collectedStartupLog = None
351  self.__collectedStartupErrorsState__collectedStartupErrorsState = False
352  self.__collectedStartupWarningsState__collectedStartupWarningsState = False
353  MLABpriv.stopLogCollect()
354 
355  # -- def _loadScriptFile --------------------------------------------------------------------{{{-
356 
358  def _loadScriptFile(self, filename):
359  self._ctx_ctx = self._testHelper_testHelper.getGlobalContext().addModule(filename)
360  if self._ctx_ctx:
361  # set dynamic property so that MeVisLab and MATE know that this is a TestCase
362  self._ctx_ctx.setProperty("IsTestCase", True)
363  self._ctx_ctx.setProperty("TestCaseName", self._testCaseName_testCaseName)
364 
365  # --------------------------------------------------------------------------------------------}}}-
366 
367  # -- def callFieldValueTestCase --------------------------------------------------------------{{{-
368 
373  def callFieldValueTestCase(self, filename, testcase):
374  fieldValueTestCaseSet = FieldValueTestCaseSet(self._ctx_ctx)
375  if not fieldValueTestCaseSet.load(filename):
376  mevis.MLAB.logError(f"Failed ot load field-value test ({filename}).")
377  else:
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.")
382 
383  # --------------------------------------------------------------------------------------------}}}-
384 
385  # -- def __createNormalTestNode ----------------------------------------------------------------------{{{-
386 
390  def __createNormalTestNode(self, virtualFunctionName, functionName, functionBaseName, functionDict, isDisabled):
391  retVal = True
392  if not functionBaseName in functionDict["names"]:
393  xmlNode = self.__getFunctionInfo__getFunctionInfo(
394  functionBaseName, functionName, isDisabled=isDisabled, sourceName=functionName
395  )
396  functionDict["names"].append(functionBaseName)
397  functionDict["nodes"][virtualFunctionName] = xmlNode
398  else:
399  mevis.MLAB.logError(f"Function with name {functionBaseName} already defined!")
400  retVal = False
401  return retVal
402 
403  # --------------------------------------------------------------------------------------------}}}-
404 
405  def _callGroupFunction(self, groupFunctionName):
406  return self._ctx_ctx.call(groupFunctionName, [])
407 
408  # -- def __createTestGroupNode ---------------------------------------------------------------{{{-
409 
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.")
417  return
418 
419  # Get the field-value test case set file.
420  functionList = self._callGroupFunction_callGroupFunction(groupFunctionName)
421  if not functionList:
422  mevis.MLAB.logError(f"Failed to build virtual functions for the {groupFunctionName} test.")
423  return
424 
425  if type(functionList) not in (list, tuple):
426  mevis.MLAB.logError(
427  f"The test group function ({groupFunctionName}) must return a list or tuple with function objects!"
428  )
429  return
430 
431  virtualGroupName = f"TEST{orderString}_{groupName}"
432  groupXMLNode = etree.Element(
433  "GroupNode", name=virtualGroupName, basename=groupName, type="TestGroup", sourceName=groupFunctionName
434  )
435  etree.SubElement(groupXMLNode, "Documentation").text = self._ctx_ctx.scriptVariable(f"{groupFunctionName}.__doc__")
436 
437  nameToFunctionMap = {}
438  for function in functionList:
439  # allow function names as string
440  if isinstance(function, str):
441  function = self._ctx_ctx.scriptVariable(function)
442  nameToFunctionMap[function.__name__] = function
443 
444  for functionName in sorted(nameToFunctionMap.keys()):
445  function = nameToFunctionMap[functionName]
446 
447  functionNodeName = functionName
448  if functionNodeName.startswith("DISABLED_"):
449  functionNodeName = functionNodeName[len("DISABLED_") :]
450 
451  if (
452  functionNodeName not in functionDict["nodes"]
453  or functionDict["nodes"][functionNodeName].tag != "Function"
454  ):
455  mevis.MLAB.logError(
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."
458  )
459  return False
460 
461  # Update function info, i.e. move the function node to the group node. The
462  # dictionary with the virtual function names must be updated too.
463  virtualFunctionName = (
464  f"{virtualGroupName}_"
465  f"{functionNodeName[4:] if not functionNodeName.startswith('DISABLED_') else functionNodeName[13:]}"
466  )
467 
468  functionNode = functionDict["nodes"][functionNodeName]
469  functionNode.set("name", virtualFunctionName)
470  # mark function as disabled if the whole group is disabled; otherwise, keep the current state of the function
471  # this way explicitly disabled functions stay disabled
472  if isDisabled:
473  functionNode.set("is_disabled", str(isDisabled))
474 
475  # Remove function from dictionary of nodes. It will be part of the group!
476  del functionDict["nodes"][functionNodeName]
477 
478  # Remove old virtual function
479  self.__functionDict__functionDict.pop(functionName)
480  self.__functionDict__functionDict[virtualFunctionName] = functionName
481 
482  groupXMLNode.append(functionNode)
483 
484  functionDict["names"].append(groupName)
485  functionDict["nodes"][virtualGroupName] = groupXMLNode
486  return True
487 
488  # --------------------------------------------------------------------------------------------}}}-
489 
490  # -- def __createFieldValueTestNode ----------------------------------------------------------{{{-
491 
496  def __createFieldValueTestNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
497  # Find all the field-value test case functions, expand them and add the
498  # single items to the virtual function list.
499  if groupName in functionDict["names"]:
500  mevis.MLAB.logError(f"A test with name {groupName} already exists. No duplicate names allowed.")
501  return
502 
503  # Get the field-value test case set file.
504  self._testHelper_testHelper.pushChangeSet()
505  retVal = self._ctx_ctx.call(functionName, [])
506  self._testHelper_testHelper.popChangeSet()
507 
508  filename, testCaseList = retVal if type(retVal) in (list, tuple) else (retVal, None)
509 
510  groupXMLNode = etree.Element(
511  "GroupNode",
512  name=virtualFunctionBaseName,
513  basename=groupName,
514  type="FieldValueTest",
515  sourceName=functionName,
516  )
517  etree.SubElement(groupXMLNode, "Documentation").text = self.getDocumentationgetDocumentation(functionName)
518 
519  # Keep in mind that duplicate names aren't allowed in field-value test case
520  # sets either.
521  functionDict["names"].append(groupName)
522  functionDict["nodes"][virtualFunctionBaseName] = groupXMLNode
523 
524  fvtcs = FieldValueTestCaseSet(self._ctx_ctx)
525  if not fvtcs.load(filename):
526  mevis.MLAB.logError(f"Failed to load the field-value test case set ({filename})!")
527  return False
528 
529  if not testCaseList:
530  for testcase in sorted(fvtcs.getList()):
531  virtualFunctionName = f"{virtualFunctionBaseName}_{testcase}"
532  groupXMLNode.append(
533  self.__getFunctionInfo__getFunctionInfo(
534  testcase,
535  virtualFunctionName,
536  (self.callFieldValueTestCasecallFieldValueTestCase, (filename, testcase)),
537  isDisabled=isDisabled,
538  sourceName=functionName,
539  )
540  )
541  else:
542  availableTestCaseList = fvtcs.getList()
543  for testcase in sorted(testCaseList):
544  if testcase in availableTestCaseList:
545  virtualFunctionName = f"{virtualFunctionBaseName}_{testcase}"
546  groupXMLNode.append(
547  self.__getFunctionInfo__getFunctionInfo(
548  testcase,
549  virtualFunctionName,
550  (self.callFieldValueTestCasecallFieldValueTestCase, (filename, testcase)),
551  isDisabled=isDisabled,
552  sourceName=functionName,
553  )
554  )
555  else:
556  mevis.MLAB.logError(f"The field-value test case {testcase} is unknown!")
557 
558  # --------------------------------------------------------------------------------------------}}}-
559 
560  # -- def __createIterativeTestNode -----------------------------------------------------------{{{-
561 
566  def __createIterativeTestNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
567  # Find all iterative test functions, expand them and add the single items
568  # to the virtual function list.
569  if groupName in functionDict["names"]:
570  mevis.MLAB.logError(f"A test with name {groupName} already exists. No duplicate names allowed.")
571  return
572 
573  # Get the iterations and the actual function to call.
574  self._testHelper_testHelper.pushChangeSet()
575  retVal = self._ctx_ctx.call(functionName, [])
576  self._testHelper_testHelper.popChangeSet()
577 
578  try:
579  iterator, function = retVal
580  except: # pylint: disable=W0702
581  mevis.MLAB.logError(
582  f"The iterative test function ({functionName}) must return a list or dictionary"
583  f" with parameters and a function to call!"
584  )
585  return
586 
587  groupXMLNode = etree.Element(
588  "GroupNode", name=virtualFunctionBaseName, basename=groupName, type="IterativeTest", sourceName=functionName
589  )
590  etree.SubElement(groupXMLNode, "Documentation").text = self.getDocumentationgetDocumentation(functionName)
591 
592  # Duplicate item nodes are not possible by design (either an index is used
593  # or a dictionary).
594  functionDict["names"].append(groupName)
595  functionDict["nodes"][virtualFunctionBaseName] = groupXMLNode
596  regExpFunctionNames = re.compile(r"^[.\w]+$")
597 
598  # Create virtual functions for given iterative test.
599  if isinstance(iterator, (list, tuple)):
600  ctr = 0
601  # Let the index used to identify the function be zero padded.
602  justificationWidth = len(unicode(len(iterator) - 1))
603  for item in iterator:
604  # The zero padded identifier.
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):
609  groupXMLNode.append(
610  self.__getFunctionInfo__getFunctionInfo(
611  virtualFunctionId,
612  virtualFunctionName,
613  (function, args),
614  isDisabled=isDisabled,
615  sourceName=functionName,
616  )
617  )
618  else:
619  mevis.MLAB.logError(
620  f"The iterative test function ({functionName}) defines non-alphanumeric virtual "
621  f"function name {virtualFunctionName}!"
622  )
623  ctr += 1
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):
629  groupXMLNode.append(
630  self.__getFunctionInfo__getFunctionInfo(
631  unicode(item),
632  virtualFunctionName,
633  (function, args),
634  isDisabled=isDisabled,
635  sourceName=functionName,
636  )
637  )
638  else:
639  mevis.MLAB.logError(
640  f"The iterative test function ({functionName}) defines non-alphanumeric virtual "
641  f"function name {virtualFunctionName}!"
642  )
643  else:
644  mevis.MLAB.logError(
645  f"The iterative test function ({functionName}) must return a list or dictionary with parameters!"
646  )
647 
648  # --------------------------------------------------------------------------------------------}}}-
649 
650  # -- def __createUnitTestWrapperNode -----------------------------------------------------------{{{-
651 
657  def __createUnitTestWrapperNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled):
658  # Find all unit test wrapper functions, expand them and add the single items
659  # to the virtual function list.
660 
661  if groupName in functionDict["names"]:
662  mevis.MLAB.logError(f"A test with name {groupName} already exists. No duplicate names allowed.")
663  return
664 
665  # Get the unit test and the actual function to call.
666  self._testHelper_testHelper.pushChangeSet()
667  suite = self._ctx_ctx.call(functionName, [])
668  self._testHelper_testHelper.popChangeSet()
669 
670  if not isinstance(suite, unittest.TestSuite):
671  mevis.MLAB.logError(f"The unit test wrapper function ({functionName}) must return a unittest.TestSuite!")
672  return
673 
674  groupXMLNode = etree.Element(
675  "GroupNode",
676  name=virtualFunctionBaseName,
677  basename=groupName,
678  type="UnitTestWrapper",
679  sourceName=functionName,
680  )
681  etree.SubElement(groupXMLNode, "Documentation").text = self.getDocumentationgetDocumentation(functionName)
682 
683  # Duplicate item nodes are not possible by design (either an index is used
684  # or a dictionary).
685  functionDict["names"].append(groupName)
686  functionDict["nodes"][virtualFunctionBaseName] = groupXMLNode
687 
688  def _isSkipped(test):
689  isClassSkipped = getattr(test.__class__, "__unittest_skip__", False)
690  testMethod = getattr(test, test._testMethodName) # pylint: disable=W0212
691  isMethodSkipped = getattr(testMethod, "__unittest_skip__", False)
692  return isClassSkipped or isMethodSkipped
693 
694  # Create virtual functions for given unit test wrapper
695  def _unpackSuite(suite):
696  allTests = []
697  for test in suite._tests: # pylint: disable=W0212
698  if isinstance(test, unittest.TestSuite):
699  allTests.extend(_unpackSuite(test))
700  else:
701  if not _isSkipped(test):
702  allTests.append(test)
703  return allTests
704 
705  allTests = _unpackSuite(suite)
706 
707  def _makeName(test):
708  testCaseName = test.__class__.__name__
709  testFunctionName = test._testMethodName # pylint: disable=W0212
710  return "{0}_{1}".format(testCaseName, testFunctionName)
711 
712  allTests.sort(key=_makeName)
713  testNames = list(map(_makeName, allTests))
714 
715  # It could be smarter to integrate this more deeply into the callTestFunction part.
716  def _runUnitTestFunction(testFunction):
717  testResult = UnitTestResult()
718  testResult._previousTestClass = self.__previousTestClass__previousTestClass
719  if self.__dummyTestSuite__dummyTestSuite is None:
720  self.__dummyTestSuite__dummyTestSuite = unittest.TestSuite()
721  # handle setup of class and module fixtures (copied from unittest.TestSuite):
722  self.__dummyTestSuite__dummyTestSuite._tearDownPreviousClass(testFunction, testResult)
723  self.__dummyTestSuite__dummyTestSuite._handleModuleFixture(testFunction, testResult)
724  self.__dummyTestSuite__dummyTestSuite._handleClassSetUp(testFunction, testResult)
725  self.__previousTestClass__previousTestClass = testFunction.__class__
726  # run test:
727  testFunction.run(testResult)
728  testResult.logResult("Test was successful")
729 
730  for testName, testFunction in zip(testNames, allTests):
731  testMethod = getattr(testFunction, testFunction._testMethodName)
732  funcXMLNode = self.__getFunctionInfo__getFunctionInfo(
733  testName,
734  "{}_{}".format(virtualFunctionBaseName, testName),
735  (_runUnitTestFunction, [testFunction]),
736  isDisabled=isDisabled,
737  )
738  if hasattr(testMethod, "__func__"): # testMethod is really a method
739  funcXMLNode.attrib["sourceFilename"] = testMethod.__func__.__code__.co_filename
740  funcXMLNode.attrib["sourceLine"] = str(testMethod.__func__.__code__.co_firstlineno)
741  elif hasattr(testMethod, "__code__"): # testMethod is actually a function
742  funcXMLNode.attrib["sourceFilename"] = testMethod.__code__.co_filename
743  funcXMLNode.attrib["sourceLine"] = str(testMethod.__code__.co_firstlineno)
744  else: # None or unsupported type - should we raise here?
745  funcXMLNode.attrib["sourceFilename"] = ""
746  funcXMLNode.attrib["sourceLine"] = "0"
747  groupXMLNode.append(funcXMLNode)
748 
749  def _callableFunctions(self):
750  return self._ctx_ctx.callableFunctions()
751 
752  # -- def __buildVirtualFunctions ---------------------------------------------------------------------{{{-
753 
758  def _buildVirtualFunctions(self, isNewlyCreated):
759  # A list containing the found function names (to prevent duplicates).
760  functionInformationDict = {"names": [], "nodes": {}}
761 
762  regExpDict = {
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+)$"),
768  }
769 
770  # The result node.
771  functionsNode = etree.SubElement(self.__xmlRoot__xmlRoot, "TestFunctions")
772 
773  # Check the optional list of disabled test functions (it is defined by the disabledTestFunction() decorator)
774  disabledFunctions = self._ctx_ctx.scriptVariable("MLABTC_DISABLED_TEST_FUNCTIONS") or []
775 
776  # The dictionary of all test functions sorted by type.
777  functionDict = {
778  "TestFunction": [],
779  "TestGroup": [],
780  "FieldValueTest": [],
781  "IterativeTest": [],
782  "UnitTestWrapper": [],
783  }
784  for functionName in self._callableFunctions_callableFunctions():
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"]),
791  ):
792  if functionName.startswith(prefix) or functionName.startswith("DISABLED_" + prefix):
793  functionList.append(functionName)
794 
795  for functionName in sorted(functionDict["TestFunction"]):
796  mObj = regExpDict["TestFunction"].match(functionName)
797  if not mObj:
798  mevis.MLAB.logError(f"Name of test function invalid ({functionName})")
799  else:
800  disabledString, orderString, functionBaseName = mObj.groups()
801  isDisabled = (disabledString is not None) or (functionName in disabledFunctions)
802  fname = f"TEST{orderString}_{functionBaseName}"
803  self.__createNormalTestNode__createNormalTestNode(
804  fname, functionName, functionBaseName, functionInformationDict, isDisabled=isDisabled
805  )
806 
807  for functionName in sorted(functionDict["TestGroup"]):
808  mObj = regExpDict["TestGroup"].match(functionName)
809  if not mObj:
810  mevis.MLAB.logError(f"Name of test group invalid ({functionName})")
811  else:
812  disabledString, orderString, groupName = mObj.groups()
813  isDisabled = (disabledString is not None) or (functionName in disabledFunctions)
814  self.__createTestGroupNode__createTestGroupNode(
815  functionName, orderString, groupName, functionInformationDict, isDisabled=isDisabled
816  )
817 
818  for functionName in sorted(functionDict["FieldValueTest"]):
819  mObj = regExpDict["FieldValueTest"].match(functionName)
820  if not mObj:
821  mevis.MLAB.logError(f"Name of field value test invalid ({functionName})")
822  else:
823  disabledString, orderString, groupName = mObj.groups()
824  isDisabled = (disabledString is not None) or (functionName in disabledFunctions)
825  fname = f"TEST{orderString}_{groupName}"
826  self.__createFieldValueTestNode__createFieldValueTestNode(
827  fname, functionName, groupName, functionInformationDict, isDisabled=isDisabled
828  )
829 
830  for functionName in sorted(functionDict["IterativeTest"]):
831  mObj = regExpDict["IterativeTest"].match(functionName)
832  if not mObj:
833  mevis.MLAB.logError(f"Name of iterative test invalid ({functionName})")
834  else:
835  disabledString, orderString, groupName = mObj.groups()
836  isDisabled = (disabledString is not None) or (functionName in disabledFunctions)
837  fname = f"TEST{orderString}_{groupName}"
838  self.__createIterativeTestNode__createIterativeTestNode(
839  fname, functionName, groupName, functionInformationDict, isDisabled=isDisabled
840  )
841 
842  for functionName in sorted(functionDict["UnitTestWrapper"]):
843  mObj = regExpDict["UnitTestWrapper"].match(functionName)
844  if not mObj:
845  mevis.MLAB.logError(f"Name of unit test wrapper invalid ({functionName})")
846  else:
847  disabledString, orderString, groupName = mObj.groups()
848  isDisabled = (disabledString is not None) or (functionName in disabledFunctions)
849  fname = f"TEST{orderString}_{groupName}"
850  self.__createUnitTestWrapperNode__createUnitTestWrapperNode(
851  fname, functionName, groupName, functionInformationDict, isDisabled=isDisabled
852  )
853 
854  # Append nodes in correct order. Essential for other methods to work
855  # properly.
856  keys = sorted(functionInformationDict["nodes"].keys())
857  if len(keys) > 0:
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}!")
862 
863  # --------------------------------------------------------------------------------------------}}}-
864 
865  # -- def __getFunctionInfo -------------------------------------------------------------------{{{-
866 
870  def __getFunctionInfo(self, functionBaseName, functionName, calledFunction=None, isDisabled=False, sourceName=""):
871  self.__functionDict__functionDict.setdefault(functionName, calledFunction)
872  functionXMLNode = etree.Element(
873  "Function", basename=functionBaseName, name=functionName, sourceName=sourceName, is_disabled=str(isDisabled)
874  )
875  documentation = self.getDocumentationgetDocumentation(functionName)
876  etree.SubElement(functionXMLNode, "Documentation").text = documentation if documentation else ""
877  return functionXMLNode
878 
879  # --------------------------------------------------------------------------------------------}}}-
880 
881  # -- def isValid -----------------------------------------------------------------------------{{{-
882 
884  def isValid(self):
885  return self.__valid__valid
886 
887  # --------------------------------------------------------------------------------------------}}}-
888 
889  # -- def hasNetwork --------------------------------------------------------------------------{{{-
890 
891  def hasNetwork(self):
892  return os.path.exists(self.networkFileNamenetworkFileName())
893 
894  # --------------------------------------------------------------------------------------------}}}-
895 
896  # -- def networkFileName --------------------------------------------------------------------------{{{-
897 
898  def networkFileName(self):
899  return self._ctx_ctx.network().filename()
900 
901  # --------------------------------------------------------------------------------------------}}}-
902 
903  # -- def openFiles ---------------------------------------------------------------------------{{{-
904 
905  def openFiles(self):
906  typeName = self.getNamegetName()
907  for fileName in self._ctx_ctx.getScriptSourceFiles():
908  mevis.MLAB.priv().openRelatedFile(typeName, fileName)
909 
910  # --------------------------------------------------------------------------------------------}}}-
911 
912  # -- def openNetwork -------------------------------------------------------------------------{{{-
913 
914  def openNetwork(self):
915  if self._ctx_ctx:
916  mevis.MLAB.priv().showIDE()
917  self._ctx_ctx.showInternalNetwork()
918 
919  # --------------------------------------------------------------------------------------------}}}-
920 
921  # -- def getType -----------------------------------------------------------------------------{{{-
922 
923  def getType(self):
924  return self._testCaseType_testCaseType
925 
926  # --------------------------------------------------------------------------------------------}}}-
927 
928  # -- def getModule -----------------------------------------------------------------------------{{{-
929 
930  def getModule(self):
931  return self._ctx_ctx
932 
933  # --------------------------------------------------------------------------------------------}}}-
934 
935  # -- def getName -----------------------------------------------------------------------------{{{-
936 
937  def getName(self):
938  return self._testCaseName_testCaseName
939 
940  # --------------------------------------------------------------------------------------------}}}-
941 
942  # -- def getListOfTestFuncs ------------------------------------------------------------------{{{-
943 
945  return sorted(self.__functionDict__functionDict.keys())
946 
947  # --------------------------------------------------------------------------------------------}}}-
948 
949  # -- def getPackage --------------------------------------------------------------------------{{{-
950 
951  def getPackage(self):
952  return self.__xmlRoot__xmlRoot.find("Package").text
953 
954  # --------------------------------------------------------------------------------------------}}}-
955 
956  # -- def getTestCaseNode ---------------------------------------------------------------------{{{-
957 
958  def getTestCaseNode(self):
959  return self.__xmlRoot__xmlRoot
960 
961  # --------------------------------------------------------------------------------------------}}}-
962 
963  # -- def __callSetUpTestCase -----------------------------------------------------------------{{{-
964 
965  def __callSetUpTestCase(self):
966  if "setUpTestCase" in self._ctx_ctx.callableFunctions():
967  self._ctx_ctx.call("setUpTestCase", [])
968 
969  # --------------------------------------------------------------------------------------------}}}-
970 
971  # -- def __callTearDownTestCase --------------------------------------------------------------{{{-
972 
973  def __callTearDownTestCase(self):
974  if "tearDownTestCase" in self._ctx_ctx.callableFunctions():
975  self._ctx_ctx.call("tearDownTestCase", [])
976 
977  # --------------------------------------------------------------------------------------------}}}-
978 
979  def __tearDown(self):
980  if self.__setupTestCaseCalled__setupTestCaseCalled:
981  mevis.MLAB.log("Calling tearDown() function...")
982  self.__callTearDownTestCase__callTearDownTestCase()
983  if self.__dummyTestSuite__dummyTestSuite:
984  # unittest support: clean up after running unittest.TestCases
985  testResult = UnitTestResult()
986  testResult._previousTestClass = self.__previousTestClass__previousTestClass
987  self.__dummyTestSuite__dummyTestSuite._tearDownPreviousClass(None, testResult)
988  self.__dummyTestSuite__dummyTestSuite._handleModuleTearDown(testResult)
989  testResult.logResult("")
990  self.__previousTestClass__previousTestClass = None
991  self.__dummyTestSuite__dummyTestSuite = None
992  if TestSupport.Logging.gStopped:
993  raise CancelTestException
994  else:
995  mevis.MLAB.log("Destroying test case context...")
996  self.destroyContextdestroyContext()
997 
998  # -- def run ---------------------------------------------------------------------------------{{{-
999 
1001  def run(self, resultNode):
1002 
1003  self.activateactivate()
1004 
1005  TestSupport.Logging.gStopped = False
1006 
1007  logHandler = self._testHelper_testHelper.getLogHandler()
1008 
1009  availTestFunctions = self.getListOfTestFuncsgetListOfTestFuncs()
1010 
1011  # Build dict mapping test function names to xml nodes.
1012  funcList = resultNode.findall(".//Function")
1013  length = len(funcList)
1014 
1015  self.__currentResultNode__currentResultNode = resultNode
1016 
1017  # Make sure the virtual test function for loading the test case is the first, if it exists.
1018  # This ensures that initial errors/warnings are appended to this function. Accordingly
1019  # the unload test case function must be last.
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:
1026  del funcList[i]
1027  funcList.insert(0, funcNode)
1028  loadTestCaseFunctionHandled = True
1029  elif not unloadTestCaseFunctionHandled and funcName == Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION:
1030  del funcList[i]
1031  funcList.append(funcNode)
1032  unloadTestCaseFunctionHandled = True
1033  if loadTestCaseFunctionHandled and unloadTestCaseFunctionHandled:
1034  break
1035 
1036  self.__setupTestCaseCalled__setupTestCaseCalled = False
1037 
1038  # Iterate over all test functions (sorted by name) that should be tested.
1039  # The iteration with an index is required to call setUpTestCase and
1040  # tearDownTestCase properly.
1041  for i in range(0, length):
1042  funcNode = funcList[i]
1043  funcName = funcNode.get("name")
1044 
1045  isLastTestFunction = i == length - 1
1046  data = RunTestFunctionData(funcNode, funcName, logHandler, isLastTestFunction)
1047 
1048  if not self.__prepareRunTestFunction__prepareRunTestFunction(data, availTestFunctions):
1049  continue
1050 
1051  self.__runTestFunction__runTestFunction(data)
1052  self.__finishRunTestFunction__finishRunTestFunction(data)
1053  if data.cancelled:
1054  # Do NOT call __tearDown() when 'Stop on error' flag is set and an error occured.
1055  if not (TestSupport.Logging.gStopOnFirstError and logHandler.numErrors() > 0):
1056  self.__tearDown__tearDown()
1057  break
1058 
1059  self.deactivatedeactivate()
1060 
1061  def __prepareRunTestFunction(self, data, availTestFunctions):
1062  if self.__perFunctionResultDirectory__perFunctionResultDirectory:
1063  funcNameForResultDir = data.funcName
1064  else:
1065  funcNameForResultDir = None
1066  self._testHelper_testHelper.setTestCaseResultDirectory(self.getNamegetName().replace("::", os.sep), funcNameForResultDir)
1067 
1068  shouldRunTestFunction = True
1069 
1070  # Verify that a function with the given name exists.
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
1077 
1078  def __runTestFunction(self, data):
1079  data.started = time.time()
1080 
1081  try:
1082  data.logHandler.startTestFunction(self.getTypegetType(), self.getNamegetName(), data.funcName)
1083  if self.__testCaseListener__testCaseListener:
1084  self.__testCaseListener__testCaseListener.startTestCaseFunction(self.getTypegetType(), self.getNamegetName(), data.funcName)
1085 
1086  MLABpriv.clearLogState()
1087 
1088  # append earlier testcase error/warnings to the first test function that is executed
1089  self.__appendCollectedStartupLog__appendCollectedStartupLog(data.logHandler)
1090 
1091  self.__setupTestCaseAndRunTestFunction__setupTestCaseAndRunTestFunction(data)
1092 
1093  if data.funcName == Utils.VIRTUAL_UNLOAD_TEST_CASE_TEST_FUNCTION:
1094  self.__tearDown__tearDown()
1095  if TestSupport.Logging.gStopped:
1096  raise CancelTestException
1097  except CancelTestException:
1098  data.cancelled = True
1099 
1100  def __finishRunTestFunction(self, data):
1101  for extraTestCaseResult in self._testHelper_testHelper.takeExtraTestCaseResults():
1102  self.addExtraTestCaseResultaddExtraTestCaseResult(extraTestCaseResult)
1103 
1104  # process events so that any delayed messages are also part of the test function
1105  mevis.MLAB.processEvents()
1106  # force messages from other threads to be printed inside of this test function execution
1107  MLABpriv.flushPendingMessages()
1108 
1109  duration = time.time() - data.started
1110 
1111  # Gather status and additional information.
1112  status = Utils.TEST_STATUS_OK
1113  if MLABpriv.hadLogWarnings() or self.__collectedStartupWarningsState__collectedStartupWarningsState:
1114  status = Utils.TEST_STATUS_WARNING
1115  if MLABpriv.hadLogErrors() or self.__collectedStartupErrorsState__collectedStartupErrorsState:
1116  status = Utils.TEST_STATUS_ERROR
1117  self.__collectedStartupErrorsState__collectedStartupErrorsState = False
1118  self.__collectedStartupWarningsState__collectedStartupWarningsState = False
1119  data.logHandler.stopTestFunction(status, duration)
1120  if self.__testCaseListener__testCaseListener:
1121  self.__testCaseListener__testCaseListener.endTestCaseFunction(status, duration)
1122 
1123  if data.cancelled:
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())
1128 
1129  def __appendCollectedStartupLog(self, logHandler):
1130  if self.__collectedStartupLog__collectedStartupLog:
1131  log = self.__collectedStartupLog__collectedStartupLog
1132  msgs = log.split("<br>")
1133  if len(msgs):
1134  mevis.MLAB.log("TestCase setup errors/warnings:")
1135  for msg in msgs:
1136  if msg != "":
1137  logHandler.appendMessage(msg)
1138  mevis.MLAB.log("TestCase execution:")
1139  self.__collectedStartupLog__collectedStartupLog = None
1140 
1141  def __setupTestCaseAndRunTestFunction(self, data):
1142  if data.funcNode.get("is_disabled", str(False)) == str(False):
1143  if not self.__setupTestCaseCalled__setupTestCaseCalled:
1144  self.__setupTestCaseCalled__setupTestCaseCalled = True
1145  self.__callSetUpTestCase__callSetUpTestCase()
1146  if TestSupport.Logging.gStopped:
1147  raise CancelTestException
1148  mevis.MLAB.log(f"Calling test function {data.funcName}()")
1149  self.__callTestFunction__callTestFunction(data.funcName)
1150  else:
1151  mevis.MLAB.log(f"Skipping disabled test function {data.funcName}()")
1152 
1153  # --------------------------------------------------------------------------------------------}}}-
1154 
1155  # -- def getDocumentation --------------------------------------------------------------------{{{-
1156 
1161  def getDocumentation(self, functionName):
1162  docu = self._ctx_ctx.scriptVariable(f"{functionName}.__doc__")
1163  testDocu = docu if docu else ""
1164  return re.sub(r"(?m)^\s+", "", testDocu)
1165 
1166  # --------------------------------------------------------------------------------------------}}}-
1167 
1168 
1169 # ----------------------------------------------------------------------------------------------}}}-
def __init__(self, funcNode, funcName, logHandler, isLastTestFunction)
Definition: TestCase.py:59
The superclass for the different test case categories.
Definition: TestCase.py:90
def __createTestGroupNode(self, groupFunctionName, orderString, groupName, functionDict, isDisabled)
Definition: TestCase.py:414
def openNetwork(self)
Open the internal network of the test case.
Definition: TestCase.py:914
def getType(self)
Return the type of this test case (generic of functional).
Definition: TestCase.py:923
def _getTestCaseInfo(self, testCaseName)
Definition: TestCase.py:214
def __setupTestCaseAndRunTestFunction(self, data)
Definition: TestCase.py:1141
def __getFunctionInfo(self, functionBaseName, functionName, calledFunction=None, isDisabled=False, sourceName="")
Definition: TestCase.py:870
def __createFieldValueTestNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled)
Definition: TestCase.py:496
def __createIterativeTestNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled)
Definition: TestCase.py:566
def run(self, resultNode)
Run the test case and store results in the given xml data structure.
Definition: TestCase.py:1001
def setTestCaseListener(self, testCaseListener)
Definition: TestCase.py:254
def networkFileName(self)
Returns the absolute file name of the attached network or an empty string if no network is attached.
Definition: TestCase.py:898
def getDocumentation(self, functionName)
Get the documentation for the given test function.
Definition: TestCase.py:1161
def openFiles(self)
Open the files associated with the test case.
Definition: TestCase.py:905
def getName(self)
Return the name of the test case.
Definition: TestCase.py:937
def __createUnitTestWrapperNode(self, virtualFunctionBaseName, functionName, groupName, functionDict, isDisabled)
Definition: TestCase.py:657
def __prepareRunTestFunction(self, data, availTestFunctions)
Definition: TestCase.py:1061
def isValid(self)
Has test case loaded without syntax errors?
Definition: TestCase.py:884
def _loadScriptFile(self, filename)
Definition: TestCase.py:358
def addExtraTestCaseResult(self, extraTestCaseResult)
Definition: TestCase.py:258
def getModule(self)
Return the module, might be None.
Definition: TestCase.py:930
def __finishRunTestFunction(self, data)
Definition: TestCase.py:1100
def _getTestFunction(self, funcName)
Definition: TestCase.py:267
def __createVirtualTestFunction(self, basename, name, documentation)
Definition: TestCase.py:205
def getTestCaseNode(self)
Return the XML node with the test case's information.
Definition: TestCase.py:958
def _buildVirtualFunctions(self, isNewlyCreated)
Definition: TestCase.py:758
def hasNetwork(self)
Check whether the test case has a network attached.
Definition: TestCase.py:891
def _callGroupFunction(self, groupFunctionName)
Definition: TestCase.py:405
def __appendCollectedStartupLog(self, logHandler)
Definition: TestCase.py:1129
def getListOfTestFuncs(self)
Get a list of test functions this test has.
Definition: TestCase.py:944
def callFieldValueTestCase(self, filename, testcase)
Call the given field-value test case from the given field-value test case set.
Definition: TestCase.py:373
def __createNormalTestNode(self, virtualFunctionName, functionName, functionBaseName, functionDict, isDisabled)
Definition: TestCase.py:390
def __callTestFunction(self, funcName)
Definition: TestCase.py:273
def getPackage(self)
Return the identifier of the package the test case is in.
Definition: TestCase.py:951
def __init__(self, testCaseName, isNewlyCreated=False)
Default constructor for the test case.
Definition: TestCase.py:121
def __del__(self)
The default destructor.
Definition: TestCase.py:219
A class collecting a set of field-value test cases.
def pushChangeSet()
Push a new ChangeSet to the stack.
Definition: Base.py:903
def popChangeSet()
Pop the last ChangeSet from the stack.
Definition: Base.py:914
Package to provide logging functions.
Definition: Logging.py:1
Adds GoogleTest like methods.
Definition: Macros.py:1