TestCenter Reference
TestHelper.py
Go to the documentation of this file.
2# Copyright 2007, 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
16
17# -- system imports ----------------------------------------------------------------------------{{{-
18import base64
19import os
20import re
21import sys
22
23import _thread
24import traceback
25
26# ----------------------------------------------------------------------------------------------}}}-
27
28# -- local imports -----------------------------------------------------------------------------{{{-
29import mevis
30
31from TestSupport.ChangeSet import ChangeSet
32from TestSupport.MessageFilters import MessageHandling, ErrorMessageFilter, WarningMessageFilter, InfoMessageFilter
33
34# ----------------------------------------------------------------------------------------------}}}-
35
36_mlab_do_not_reload = True # exempt this module from Python module reloading, value is currently ignored
37
38gEnablePrettyLogging = False
39gLogInfoMessages = True
40
41
43 """Stores an additional message (usually the unformatted version) with a log message."""
44
45 specialMessageMarker = re.compile(r".*<MLAB TC=(\d+)\/>")
46 currentSpecialMessageId = 0
47 specialMessages = {}
48
49 @classmethod
50 def add(cls, message, specialMessage):
52 message += f"<MLAB TC={cls.currentSpecialMessageId}/>"
53 cls.specialMessages[cls.currentSpecialMessageId] = specialMessage
54 return message
55
56 @classmethod
57 def get(cls, message):
58 match = re.match(cls.specialMessageMarker, message)
59 if match:
60 messageId = int(match.group(1))
61 specialMessage = cls.specialMessages.get(messageId, None)
62 if specialMessage is not None:
63 del cls.specialMessages[messageId]
64 return specialMessage
65 return None
66
67
68def emitSpecialMessage(loggingMethod, file, line, type, message, escapeHtml=True, formattedStack=""):
69 if escapeHtml:
70 escapedMsg = mevis.MLAB.escapeString(message)
71 escapedMsg = escapedMsg.replace("\n", "<br>")
72 else:
73 escapedMsg = message
74
75 if sys.version_info.major >= 3:
76 if isinstance(formattedStack, str):
77 formattedStack = formattedStack.encode()
78
79 encodedStackTrace = str(base64.b64encode(formattedStack))
80 # store internal message to be used from LogHandler:
81 specialMessage = "##M[%s|%s|%s|%s]: %s" % (file, line, type, encodedStackTrace, escapedMsg)
82 if gEnablePrettyLogging:
83 escapedMsg = (
84 "<font style='font-weight:normal'><font color=black>"
85 + mevis.MLAB.createHyperLinkWithLine(file, line)
86 + "("
87 + str(line)
88 + "):</font></font> "
89 + escapedMsg
90 )
91 loggingMethod(SpecialMessage.add(escapedMsg, specialMessage))
92 else:
93 loggingMethod(specialMessage)
94
95
96def emitSpecialCommand(file, line, type, fileList, message, escapeHtml=True):
97 if escapeHtml:
98 escapedMsg = mevis.MLAB.escapeString(message)
99 else:
100 escapedMsg = message
101
102 # store internal message to be used from LogHandler:
103 specialMessage = "##C[%s|%s|%s:%s] %s" % (file, line, type, ",".join(fileList), str(escapedMsg))
104 if gEnablePrettyLogging:
105 escapedMsg = (
106 "<font style='font-weight:normal'><font color=black>"
107 + mevis.MLAB.createHyperLinkWithLine(file, line)
108 + "("
109 + str(line)
110 + "):</font></font> "
111 + escapedMsg
112 )
113 for fileInList in fileList:
114 if "|" in fileInList:
115 fileInList = fileInList[fileInList.index("|") + 1 :]
116 escapedMsg += " " + mevis.MLAB.createHyperLink(fileInList)
117 escapedMsg = SpecialMessage.add(escapedMsg, specialMessage)
118 mevis.MLAB.logHTML(escapedMsg)
119 else:
120 mevis.MLAB.logHTML(specialMessage)
121
122
123def UseStackFrameFromCallerForLogging(func):
124 """This decorator is used to specify the stack frame that is used to detect the location while logging.
125 It uses the stack frame that calls the given function. Functions with this decorator can call each other
126 recursively. The first stack frame of such a recursion is then used."""
127
128 def setLoggingCallerStackFrameWrapper(*args, **kwargs):
130 return func(*args, **kwargs)
131
132 return setLoggingCallerStackFrameWrapper
133
134
135# Alias for backward compatibility of old TestCases
136IncreaseLoggingStackDepthDecorator = UseStackFrameFromCallerForLogging
137
138
140 def __init__(self, stackDepth, optional=False):
141 self.__testHelper = TestHelper.getInstance()
142 self.__stackDepth = stackDepth
143 self.__hasSetStackFrame = False
144 self.__optional = optional
145
146 def __enter__(self):
147 if not self.__testHelper.hasCallerStackFrame() or not self.__optional:
148 stackFrame = self.getCallingStackFrame(self.__stackDepth + 1)
149 self.__testHelper.pushCallerStackFrame(stackFrame)
150 self.__hasSetStackFrame = True
151
152 def __exit__(self, *_):
153 if self.__hasSetStackFrame:
154 self.__testHelper.popCallerStackFrame()
155
156 def getCallingStackFrame(self, stackDepth):
157 return sys._getframe(stackDepth + 1)
158
159
160# Returns pattern attribute or repr(exp) if the object does not have a pattern
162 try:
163 result = exp.pattern
164 except:
165 result = repr(exp)
166 return result
167
168
169# Helper object to supress errors,
170# make sure that you call handleResult() in a finally: clause
171# If no logErrorFunc it given, matching error will just be ignored, not expected, so no error will be logged if no match was found.
173 def __init__(self, errorRegExp, logErrorFunc, preventReplacingMessageSeverity=False):
174 self.__logErrorFunc = logErrorFunc
175 self.__errorRegExp = errorRegExp
176 handling = MessageHandling.EXPECT if logErrorFunc is not None else MessageHandling.IGNORE
177 self.__messageFilter = ErrorMessageFilter(handling, errorRegExp)
178 self.__preventReplacingMessageSeverity = preventReplacingMessageSeverity
180 self.__enableErrorHandling(True)
181
182 def __enableErrorHandling(self, enable):
183 logHandler = TestHelper.getInstance().getLogHandler()
184 logHandler.pushOrPopMessageFilter(enable, self.__messageFilter)
186 if enable:
187 self.__previousKeepMessageSeverity = logHandler.setKeepMessageSeverity(True)
188 else:
189 if self.__previousKeepMessageSeverity != None:
190 logHandler.setKeepMessageSeverity(self.__previousKeepMessageSeverity)
192
193 def handleResult(self):
194 mevis.MLAB.priv().flushPendingMessages()
195 hasCaughtError = self.__messageFilter.hadMatch
196 self.__enableErrorHandling(False)
197 if self.__logErrorFunc and not hasCaughtError:
198 self.__logErrorFunc("Expected error did not occur: " + regexpToString(self.__errorRegExp))
199 return hasCaughtError
200
201
203 """Helper object to supress warnings.
204 Make sure that you call handleResult() in a finally: clause.
205 If no logErrorFunc it given, matching warnings will just be ignored, not expected,
206 so no error will be logged if no match was found.
207 """
208
209 def __init__(self, warningRegExp, logErrorFunc=None, expectWarning=True):
210 self.__logErrorFunc = logErrorFunc
211 handling = MessageHandling.EXPECT if logErrorFunc is not None else MessageHandling.IGNORE
212 self.__warningRegExp = warningRegExp
213 self.__expectWarning = expectWarning
214 self.__messageFilter = WarningMessageFilter(handling, warningRegExp)
215 self.__enableWarningHandling(True)
216
217 def __enableWarningHandling(self, enable):
218 TestHelper.getInstance().getLogHandler().pushOrPopMessageFilter(enable, self.__messageFilter)
219
220 def handleResult(self):
221 mevis.MLAB.priv().flushPendingMessages()
222 hasCaughtWarning = self.__messageFilter.hadMatch
223 self.__enableWarningHandling(False)
224 if self.__logErrorFunc and hasCaughtWarning != self.__expectWarning:
225 if self.__expectWarning:
226 self.__logErrorFunc("Expected warning did not occur: " + regexpToString(self.__warningRegExp))
227 else:
228 self.__logErrorFunc("Unexpected warning did occur: " + regexpToString(self.__warningRegExp))
229
230 return hasCaughtWarning == self.__expectWarning
231
232
233# Helper object to expect infos,
234# make sure that you call handleResult() in a finally: clause
236 def __init__(self, infoRegExp, allowUnexpectedMessages, logErrorFunc):
237 self.__infoRegExp = infoRegExp
238 self.__allowUnexpectedMessages = allowUnexpectedMessages
239 self.__logErrorFunc = logErrorFunc
240 self.__messageFilter = InfoMessageFilter(MessageHandling.EXPECT, infoRegExp, allowUnexpectedMessages)
241 self.__enableInfoHandling(True)
242
243 def __enableInfoHandling(self, enable):
244 TestHelper.getInstance().getLogHandler().pushOrPopMessageFilter(enable, self.__messageFilter)
245
246 def handleResult(self):
247 mevis.MLAB.priv().flushPendingMessages()
248 hadUnexpectedInfo = self.__messageFilter.hadNonMatch
249 hadExpectedInfo = self.__messageFilter.hadMatch
250 self.__enableInfoHandling(False)
251 if hadUnexpectedInfo:
252 if not self.__allowUnexpectedMessages:
253 self.__logErrorFunc("Unexpected info message occurred")
254 if not hadExpectedInfo:
255 self.__logErrorFunc("Expected info message did not occur: " + regexpToString(self.__infoRegExp))
256
257
258# -- class TC_ChangeSet ------------------------------------------------------------------------{{{-
260 # -- def __init__ ----------------------------------------------------------------------------{{{-
261
263 def __init__(self, context):
264 ChangeSet.__init__(self, context)
265
266 # --------------------------------------------------------------------------------------------}}}-
267
268 # -- def _logDecorator -----------------------------------------------------------------------{{{-
269 def _logDecorator(func):
270 def wrapper(*args, **kwds):
272 loggingMethod, message = func(*args, **kwds)
273 if gLogInfoMessages or (loggingMethod != mevis.MLAB.logHTML):
274 stackFrame = TestHelper.getInstance().getCallerStackFrame()
275 stackLine = traceback.extract_stack(stackFrame, 1)[0]
276 emitSpecialMessage(loggingMethod, stackLine[0], stackLine[1], "ChangeSet", message, escapeHtml=True)
277
278 return wrapper
279
280 # --------------------------------------------------------------------------------------------}}}-
281
282 # -- def _logInfo ----------------------------------------------------------------------------{{{-
283 @_logDecorator
284 def _logInfo(self, message):
285 return mevis.MLAB.logHTML, message
286
287 # --------------------------------------------------------------------------------------------}}}-
288
289 # -- def _logError ---------------------------------------------------------------------------{{{-
290 @_logDecorator
291 def _logError(self, message):
292 return mevis.MLAB.logErrorHTML, message
293
294 # --------------------------------------------------------------------------------------------}}}-
295
296
297# ----------------------------------------------------------------------------------------------}}}-
298
299
300# Exception that is raised when a test execution is cancelled.
301# This may happen because of the stop-on-first-error feature
302# or because the user cancels a test run.
303class CancelTestException(Exception):
304 pass
305
306
307# -- class TestHelper --------------------------------------------------------------------------{{{-
308
313 # -- member variables ------------------------------------------------------------------------{{{-
314
315 _mCtx = None
316
317 _mTestCaseContext = None
318
319 _mHelperModule = None
320
321 _mResultDirectory = None
322
323 _mPackageList = None
324
325
326 _mTestCaseName = None
327
328 _mModuleName = None
329
330
331 _mTestCaseDataDirectory = None
332
333 _mTestCaseResultDirectory = None
334
335
336 _mChangeSetStack = None
337
338
339 _mSecureTesting = False
340
341
342 _mLogHandler = None
343
344
346 _mStackFrameStack = None
347
348
349 _mEnvironmentStack = None
350
351
352 _mExtraTestCaseResults = None
353
354
355 _mMacrosLogOnSuccess = True
356
357
358 __lockObj = _thread.allocate_lock()
359
360 __instance = None
361 # --------------------------------------------------------------------------------------------}}}-
362
363 # -- def __new__ -----------------------------------------------------------------------------{{{-
364
365 def __new__(self, *args, **kargs):
366 return self.getInstance(*args, **kargs)
367
368 # --------------------------------------------------------------------------------------------}}}-
369
370 # -- def __init__ ----------------------------------------------------------------------------{{{-
371
374 def __init__(self, *args, **kargs):
375 pass
376
377 # --------------------------------------------------------------------------------------------}}}-
378
379 # -- def getInstance -------------------------------------------------------------------------{{{-
380
381 @classmethod
382 def getInstance(self, *args, **kargs):
383 """Static method to have a reference to **THE UNIQUE** instance"""
384 if len(kargs) not in (0, 2):
385 raise Exception(
386 "Singleton's getInstance must be called with context and result directory arguments or without any!"
387 )
388
389 initialize = len(kargs) == 2
390 # Critical section start
391 self.__lockObj.acquire()
392 try:
393 if self.__instance is None:
394 # (Some exception may be thrown...)
395 if not "context" in kargs or not "resultDir" in kargs:
396 raise Exception("Singleton must be initialized with context and result directory!")
397 # Initialize **the unique** instance
398 self.__instance = object.__new__(self)
399
400 if initialize:
401 """Initialize object **here**, as you would do in __init__()..."""
402 self._mResultDirectory = kargs["resultDir"]
403 self._mCtx = kargs["context"]
404
405 # The FunctionalTesting module contains some helpful modules that are used in the methods.
406 if self._mHelperModule:
407 self._mHelperModule.remove()
408 self._mHelperModule = self._mCtx.addModule(mevis.MLAB.moduleLiteral("TestCenterHelperModule"))
409
410 self._mChangeSetStack = []
411 self._mEnvironmentStack = []
412 self._mStackFrameStack = []
413
414 finally:
415 # Exit from critical section whatever happens
416 self.__lockObj.release()
417 # Critical section end
418 return self.__instance
419
420 # --------------------------------------------------------------------------------------------}}}-
421
422 # -- def hasInstance -------------------------------------------------------------------------{{{-
423
424 @classmethod
425 def hasInstance(self):
426 return self.__instance is not None
427
428 # --------------------------------------------------------------------------------------------}}}-
429
430 # -- def setPackageList ----------------------------------------------------------------------{{{-
431
432 def setPackageList(self, packageList):
433 self._mPackageList = packageList
434
435 # --------------------------------------------------------------------------------------------}}}-
436
437 # -- def getPackageList ----------------------------------------------------------------------{{{-
438
439 def getPackageList(self):
440 return self._mPackageList
441
442 # --------------------------------------------------------------------------------------------}}}-
443
444 # -- def getGlobalContext --------------------------------------------------------------------{{{-
446 return self._mCtx
447
448 # --------------------------------------------------------------------------------------------}}}-
449
450 # -- def setTestCaseContext ------------------------------------------------------------------{{{-
451
452 def setTestCaseContext(self, ctx):
453 self._mTestCaseContext = ctx
455 self._mExtraTestCaseResults = []
456
457 # --------------------------------------------------------------------------------------------}}}-
458
459 # -- def setMacrosLogOnSuccess ---------------------------------------------------------------{{{-
460 def setMacrosLogOnSuccess(self, macrosLogOnSuccess):
462
463 # --------------------------------------------------------------------------------------------}}}-
464
465 # -- def getMacrosLogOnSuccess ---------------------------------------------------------------{{{-
469 # --------------------------------------------------------------------------------------------}}}-
470
471 # -- def getTestCaseContext ------------------------------------------------------------------{{{-
472
473 def getTestCaseContext(self):
474 return self._mTestCaseContext
475
476 # --------------------------------------------------------------------------------------------}}}-
477
478 # -- def getHelperContext --------------------------------------------------------------------{{{-
480 return self._mHelperModule
481
482 # --------------------------------------------------------------------------------------------}}}-
483
484 # -- def getResultDirectory ------------------------------------------------------------------{{{-
485 def getResultDirectory(self):
486 return self._mResultDirectory
487
488 # --------------------------------------------------------------------------------------------}}}-
489
490 # -- def setModuleName -----------------------------------------------------------------------{{{-
491 def setModuleName(self, moduleName):
492 self._mModuleName = moduleName
493
494 # --------------------------------------------------------------------------------------------}}}-
495
496 # -- def getModuleName -----------------------------------------------------------------------{{{-
497 def getModuleName(self):
498 return self._mModuleName
499
500 # --------------------------------------------------------------------------------------------}}}-
501
502 # -- def setTestCaseName ---------------------------------------------------------------------{{{-
503 def setTestCaseName(self, testCaseName):
504 self._mTestCaseName = testCaseName
505
506 # --------------------------------------------------------------------------------------------}}}-
507
508 # -- def getTestCaseName ---------------------------------------------------------------------{{{-
510 return self._mTestCaseName
511
512 # --------------------------------------------------------------------------------------------}}}-
513
514 # -- def setTestCaseDataDirectory ------------------------------------------------------------{{{-
515 def setTestCaseDataDirectory(self, testCaseDataPath):
516 self._mTestCaseDataDirectory = testCaseDataPath
517
518 # --------------------------------------------------------------------------------------------}}}-
519
520 # -- def getTestCaseDataDirectory ------------------------------------------------------------{{{-
522 return self._mTestCaseDataDirectory
523
524 # --------------------------------------------------------------------------------------------}}}-
525
526 # -- def setTestCaseResultDirectory ------------------------------------------------------------{{{-
527 def setTestCaseResultDirectory(self, testCaseName, functionName):
528 self._mTestCaseResultDirectory = os.path.join(self.getResultDirectory(), "files", testCaseName)
529 if functionName != None:
530 self._mTestCaseResultDirectory = os.path.join(self._mTestCaseResultDirectory, functionName)
531
532 # --------------------------------------------------------------------------------------------}}}-
533
534 # -- def getTestCaseResultDirectory ------------------------------------------------------------{{{-
536 if self._mTestCaseResultDirectory and not os.path.isdir(self._mTestCaseResultDirectory):
537 os.makedirs(self._mTestCaseResultDirectory)
538 return self._mTestCaseResultDirectory
539
540 # --------------------------------------------------------------------------------------------}}}-
541
542 # -- def pushChangeSet -----------------------------------------------------------------------{{{-
543
545 def pushChangeSet(self):
547 return len(self._mChangeSetStack) - 1
548
549 # --------------------------------------------------------------------------------------------}}}-
550
551 # -- def popChangeSet ------------------------------------------------------------------------{{{-
552
555 def popChangeSet(self):
556 retVal = True
557 if len(self._mChangeSetStack) > 0:
558 cs = self._mChangeSetStack.pop()
559 cs.autoRevert()
560 else:
561 retVal = False
562 return retVal
563
564 # --------------------------------------------------------------------------------------------}}}-
565
566 # -- def popChangeSet ------------------------------------------------------------------------{{{-
567
568 def clearChangeSet(self):
569 for changeSet in self._mChangeSetStack:
570 changeSet.enableAutoRevert(False)
571 while self.popChangeSet():
572 pass
573
574 # --------------------------------------------------------------------------------------------}}}-
575
576 # -- def getChangeSet ------------------------------------------------------------------------{{{-
577
578 def getChangeSet(self):
579 retVal = None
580 if len(self._mChangeSetStack) > 0:
581 retVal = self._mChangeSetStack[-1]
582 return retVal
583
584 # --------------------------------------------------------------------------------------------}}}-
585
586 # -- def getChangeSetStackLength -------------------------------------------------------------{{{-
587
590 return len(self._mChangeSetStack)
591
592 # --------------------------------------------------------------------------------------------}}}-
593
594 # -- def runTestInCurrentMlabInstance -----------------------------------------------------------------------{{{-
595
599 # --------------------------------------------------------------------------------------------}}}-
600
601 # -- def runTestInCurrentMlabInstance -----------------------------------------------------------------------{{{-
602
606 # --------------------------------------------------------------------------------------------}}}-
607
608 # -- def runTestInCurrentMlabInstance -----------------------------------------------------------------------{{{-
609
613 # --------------------------------------------------------------------------------------------}}}-
614
615 # -- def setLogHandler -----------------------------------------------------------------------{{{-
616
618 def setLogHandler(self, logHandler):
619 self._mLogHandler = logHandler
620
621 # --------------------------------------------------------------------------------------------}}}-
622
623 # -- def unsetLogHandler ---------------------------------------------------------------------{{{-
624
626 self._mLogHandler = None
627
628 # --------------------------------------------------------------------------------------------}}}-
629
630 # -- def getLogHandler -----------------------------------------------------------------------{{{-
631
634 def getLogHandler(self):
635 return self._mLogHandler
636
637 # --------------------------------------------------------------------------------------------}}}-
638
639 def pushCallerStackFrame(self, stackFrame):
640 self._mStackFrameStack.append(stackFrame)
641
643 return self._mStackFrameStack[-1] if self._mStackFrameStack else None
644
646 return len(self._mStackFrameStack) > 0
647
649 self._mStackFrameStack.pop()
650
651 # -- def addExtraTestCaseResult --------------------------------------------------------------{{{-
652 def addExtraTestCaseResult(self, extraTestCaseResult):
653 self._mExtraTestCaseResults.append(extraTestCaseResult)
654
655 # --------------------------------------------------------------------------------------------}}}-
656
657 # -- def takeExtraTestCaseResults ------------------------------------------------------------{{{-
660 self._mExtraTestCaseResults = []
661 return l
662
663 # --------------------------------------------------------------------------------------------}}}-
664
665 # -- def pushEnvironment ---------------------------------------------------------------------{{{-
666
668 self._mEnvironmentStack.append(os.environ)
669 os.environ = dict(os.environ)
670
671 # --------------------------------------------------------------------------------------------}}}-
672
673 # -- def popEnvironment ----------------------------------------------------------------------{{{-
674
676 def popEnvironment(self):
677 if len(self._mEnvironmentStack) > 0:
678 os.environ = self._mEnvironmentStack.pop()
679 return True
680 return False
681
682 # --------------------------------------------------------------------------------------------}}}-
683
684
685# ----------------------------------------------------------------------------------------------}}}-
Class to handle field changes and make them revertable.
Definition ChangeSet.py:29
__init__(self, infoRegExp, allowUnexpectedMessages, logErrorFunc)
__init__(self, stackDepth, optional=False)
Stores an additional message (usually the unformatted version) with a log message.
Definition TestHelper.py:42
add(cls, message, specialMessage)
Definition TestHelper.py:50
__init__(self, errorRegExp, logErrorFunc, preventReplacingMessageSeverity=False)
Helper object to supress warnings.
__init__(self, warningRegExp, logErrorFunc=None, expectWarning=True)
__init__(self, context)
The default constructor.
pushChangeSet(self)
Push a new ChangeSet to the stack.
pushCallerStackFrame(self, stackFrame)
popEnvironment(self)
Pops an environment dictionary from the stack and makes it the current environment.
getLogHandler(self)
Get the current log handler.
bool _mSecureTesting
Allow checking, whether tests are run in secure mode.
_mHelperModule
The context of the helper module.
_mTestCaseName
The name of the current test case.
setLogHandler(self, logHandler)
Set the current log handler.
setTestCaseName(self, testCaseName)
_mChangeSetStack
A stack of ChangeSets used to revert changes to field values.
_mExtraTestCaseResults
A list of extra test case results.
setMacrosLogOnSuccess(self, macrosLogOnSuccess)
bool _mMacrosLogOnSuccess
This is the default value for the 'logOnSuccess' parameter (if it is None) of the ASSERT_*/EXPECT_* m...
__new__(self, *args, **kargs)
The new method.
clearChangeSet(self)
Clear the change set stack without restoring the field values.
popChangeSet(self)
Pop a ChangeSet from the stack and delete it.
__init__(self, *args, **kargs)
The default constructor.
_mEnvironmentStack
A stack of environment dictionaries used to revert changes to the environment.
_mModuleName
The name of the currently tested module.
setTestCaseContext(self, ctx)
Set the context of the test.
getChangeSet(self)
Return the ChangeSet on top of the stack.
_mTestCaseContext
The current test's context.
runTestInCurrentMlabInstance(self)
Set if tests are not run in secure mode.
_mStackFrameStack
The stack frame of the calling function that is used when logging events.
getChangeSetStackLength(self)
Get the length of the ChangeSet stack.
_mTestCaseDataDirectory
The path to the test case data.
setPackageList(self, packageList)
Set the list of available packages.
addExtraTestCaseResult(self, extraTestCaseResult)
pushEnvironment(self)
Pushes the current environment to the stack.
testIsRunInSecureMode(self)
Check if tests are run in secure mode.
setTestCaseResultDirectory(self, testCaseName, functionName)
hasInstance(self)
Check if an instance has been initialized.
getPackageList(self)
Return the list of available packages.
unsetLogHandler(self)
Unset the current log handler.
setTestCaseDataDirectory(self, testCaseDataPath)
_mPackageList
The list of packages that should be assumed to be available.
getInstance(self, *args, **kargs)
The default constructor.
_mTestCaseResultDirectory
The path to the results.
_mLogHandler
The log handler that can be used to handle the reports.
runTestInSecureMode(self)
Set if tests are run in secure mode.
_mResultDirectory
The directory used to save results.
A singleton to provide important data for the testing process.