11 from builtins
import str
12 from builtins
import range
14 """Tools for running MeVisLab tests as Python unit tests
16 The functions, decorators and classes defined in this module allow you to
17 wrap your MeVisLab FunctionalTestCase in a unittest.TestCase so that the
18 test case can be executed using the standard Python unit testing framework.
20 To wrap a FunctionalTestCase in a unittest.TestCase add the following at the
21 end of the test case file.
23 from TestSupport import PythonUnitTest
25 @PythonUnitTest.addTestsToMeVisLabTestCase(globals())
26 class NameOfFunctionalTestCase(PythonUnitTest.MeVisLabTestCase):
29 @note: NameOfFunctionalTestCase has to be identical with the name of the
30 FunctionalTestCase specified in the .def file. Otherwise, the MeVisLab
31 TestCenter that is used to execute the tests will not find the tests.
33 The above is sufficient to allow PyCharm(TM) to run your MeVisLab functional
34 tests as any other Python unit tests.
36 If you also want to run your tests from the command line, then, additionally,
37 add the following at the end of the file with the MeVisLab tests (just as for
38 any old Python unit test).
40 if __name__ == '__main__':
44 @note: Wrapping ITERATIVETEST functions only works if the generation of the
45 test dictionary returned by the ITERATIVETEST function does not require
46 functionality that only works if the test runs in MeVisLab. For example,
47 TestSupport.Base.getDataDirectory() cannot be used in ITERATIVETEST. Instead
48 you can use something like
51 # use __file__ if running outside of MeVisLab (where Base.getDataDirectory() doesn't work)
52 dataDirectory = os.path.join(os.path.dirname(__file__), 'Data')
54 # use Base.getDataDirectory() if running in MeVisLab (where __file__ is not set)
55 dataDirectory = Base.getDataDirectory()
66 from xml.etree
import cElementTree
as ElementTree
69 mlabroot = os.environ.get(
'MLAB_ROOT')
72 @unittest.skip('Test is marked as DISABLED')
77 NormalTestRegExp = re.compile(
r'^(?:DISABLED_)?TEST(\d*_\w+)$')
78 IterativeTestRegExp = re.compile(
r'^(?:DISABLED_)?ITERATIVETEST(\d*_\w+)$')
82 def inner(testCaseClass):
84 runningInsideMeVisLab = hasattr(globals.get(
'ctx'),
'name')
85 if runningInsideMeVisLab:
88 MLABTC_DISABLED_TEST_FUNCTIONS = globals.get(
'MLABTC_DISABLED_TEST_FUNCTIONS', [])
90 skip = name.startswith(
'DISABLED_')
or name
in MLABTC_DISABLED_TEST_FUNCTIONS
91 m = NormalTestRegExp.match(name)
94 testCaseClass.addTest(testName, skip)
96 m = IterativeTestRegExp.match(name)
99 testDict = globals[name]()[0]
100 if isinstance(testDict, (list, tuple)):
102 width = len(str(len(testDict)-1))
103 testDict = [str(n).zfill(width)
for n
in range(len(testDict))]
105 testName =
'%s_%s' % (basename, key)
106 testCaseClass.addTest(testName, skip)
117 super(MeVisLabTestCase, self).
__init__(methodName)
120 raise Exception(
'MLAB_ROOT is not defined')
122 testCenterAdvancedPath = os.path.join(mlabroot,
'MeVisLab',
'Standard',
'Modules',
'Macros',
'Tests',
'TestCenterAdvanced')
123 if not testCenterAdvancedPath
in sys.path:
124 sys.path.insert(0, testCenterAdvancedPath)
130 configFilename = os.path.join(cls.
tempDirectorytempDirectory,
'tc_config.xml')
132 executablePath=os.path.join(mlabroot,
'MeVisLab'),
138 env = _getEnvironmentForTestCenter(mlabroot)
140 logging.basicConfig(level=logging.INFO,
141 format=
'%(asctime)s %(levelname)-8s %(message)s')
142 logging.getLogger(
'TestCenter').disabled =
True
144 from Master
import Master
145 cls.
mastermaster =
Master(cfgFile=configFilename, slaveEnvironment=env)
149 if cls.
mastermaster
is not None:
150 cls.
mastermaster.stopSlave()
157 testFuncName =
'test%s' % testName
159 testFunc = skippedDummyTest
161 testIdentifier = (cls.__name__,
'TEST%s' % testName)
163 setattr(cls, testFuncName, testFunc)
167 def formatStack(event):
168 stack = event.find(
'Stack')
169 stackText = stack.text
if stack
is not None else 'No stack trace available'
170 return 'Stack trace (most recent call last):\n%s' % stackText
172 def runTestMethod(testCaseInstance):
173 cls.
mastermaster.setTestCases([cls.__name__])
174 testFunctionDict = {testIdentifier[0]: [testIdentifier[1]]}
175 result = testCaseInstance.master.run(testFunctionDict, stopSlaveAfterTestRun=
False)
176 testCaseInstance.master.reset()
179 raise Exception(
"Test failed: TestRun did not return anything.")
182 functionNode = result.find(
'Results/TestCase/Function')
183 if functionNode
is None:
184 raise Exception(
'No function found in\n%s' % ElementTree.tostring(result))
186 if functionNode.get(
'is_disabled') ==
'True':
187 raise unittest.SkipTest(
'Skipped for unknown reasons. No test method should have been created for this test.')
190 status = int(functionNode.get(
'status'))
192 messages.append(
'%s failed' % testIdentifier[1])
194 messages.append(
'Test timed out')
196 messages.append(
'MeVisLab crashed')
199 for event
in functionNode.iter(
'Event'):
200 eventType = event.get(
'type')
203 timestamp = event.get(
'timestamp')
204 eventMessageText = _stripTags(event.find(
'Message').text)
205 if eventType ==
'Info':
207 elif eventType ==
'Warning':
208 print(
'%s %s: %s' % (timestamp, eventType, eventMessageText))
209 elif eventType
in [
'Error',
'ML Error',
'Timeout',
'Crashed',
'ScriptError',
'SemanticError']:
210 messages.append(
'%s: %s' % (eventType, eventMessageText))
211 messages.append(formatStack(event))
213 print(
'Unknown event type "%s"' % eventType)
214 print(
'%s %s: %s' % (timestamp, eventType, eventMessageText))
218 testCaseInstance.fail(
'\n'.join(messages))
219 if status == 3
or status == 4:
220 raise Exception(
'\n'.join(messages))
222 runTestMethod.__name__ = testFuncName
231 config = Config.Configuration(configFilename, autoSave=
False)
232 config.setMLABExecutablePath(executablePath)
233 config.setResultDir(resultDirectory)
234 config.getReportOptions().directory = reportDirectory
238 def _getEnvironmentForTestCenter(mlabroot):
239 buildSystemRoot = os.path.join(mlabroot,
'MeVis',
'BuildSystem',
'Sources')
240 sys.path.insert(0, buildSystemRoot)
242 import BuildSystem.SystemUtils
245 sys.path.remove(buildSystemRoot)
247 testCenterEnvironment = dict(os.environ)
248 if testCenterEnvironment.get(
'PYCHARM_HOSTED') ==
'1':
250 del testCenterEnvironment[
'PYTHONPATH']
252 requiredPackages = [
'MeVis/ThirdParty',
'MeVis/Foundation',
'MeVisLab/IDE']
253 additionalBinPaths = [os.path.join(mlabroot, package,
'bin')
for package
in requiredPackages]
254 additionalBinPaths.append(os.path.join(mlabroot,
'MeVis/ThirdParty/Sources/Qt4/qt/bin'))
255 additionalLibPaths = [os.path.join(mlabroot, package,
'lib')
for package
in requiredPackages]
256 additionalLibPaths.append(os.path.join(mlabroot,
'MeVis/ThirdParty/Python'))
257 additionalLibPaths.append(os.path.join(mlabroot,
'MeVis/ThirdParty/Sources/Qt4/qt/lib'))
258 additionalBinPaths = [os.path.normpath(path)
for path
in additionalBinPaths]
259 additionalLibPaths = [os.path.normpath(path)
for path
in additionalLibPaths]
260 BuildSystem.SystemUtils.addPathsToExecutableSearchPaths(additionalBinPaths, environmentDict=testCenterEnvironment)
261 BuildSystem.SystemUtils.addPathsToLibrarySearchPaths(additionalLibPaths, environmentDict=testCenterEnvironment)
263 return testCenterEnvironment
266 _stripTagsRE = re.compile(
r'(<!--.*?-->|<[^>]*>)')
269 """ Strips HTML tags from the given string.
270 Warning: This function is not fool-proof. It is only meant to handle well-formed HTML in MeVisLab log messages.
272 return _stripTagsRE.sub(
'', s)
def addTest(cls, testName, skip)
def createRunTestMethod(cls, testFuncName, testIdentifier)
def __init__(self, methodName='runTest')
The master instance of the TestCenter.
def writeTestCenterConfigFile(configFilename, executablePath='', resultDirectory='', reportDirectory='')
def addTestsToMeVisLabTestCase(globals)