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