-
Notifications
You must be signed in to change notification settings - Fork 2
/
AllTestLauncherSat.py
executable file
·365 lines (315 loc) · 10.5 KB
/
AllTestLauncherSat.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2008-2018 CEA/DEN
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# See http://www.salome-platform.org or email : [email protected]
"""
Test all SAT unittest files (test*.py) existing in subdirectories of a root directory
| Example:
| >> AllTestLauncherSat.py --rootPath='.' --pattern='test_???_*.py'
"""
"""
#### base of algorithm functionality
#see http://www.voidspace.org.uk/python/articles/introduction-to-unittest.shtml
import unittest
import test_something
import test_something2
import test_something3
loader = unittest.TestLoader()
suite = loader.loadTestsFromModule(test_something)
suite.addTests(loader.loadTestsFromModule(test_something2))
suite.addTests(loader.loadTestsFromModule(test_something3))
runner = unittest.TextTestRunner(verbosity=2)
result = runner.run(suite)
"""
import os
import sys
import unittest
import traceback
import argparse as AP
import glob
import fnmatch
import pprint as PP #pretty print
import src
debug = False
verboseImport = True
# get path to origin sources
defaultdir = os.path.dirname(os.path.realpath(__file__))
# get path to salomeTools sources
satdir = defaultdir
srcdir = os.path.join(satdir, 'src')
cmdsdir = os.path.join(satdir, 'commands')
# Make the src & commands package accessible from all code
sys.path.insert(0, satdir)
sys.path.insert(0, srcdir) # TODO remove that
sys.path.insert(0, cmdsdir) # TODO remove that
_user = src.architecture.get_user()
# wambeke is christian at home
_developers = ["christian", "wambeke",] # ...who wants
def errPrint(aStr):
"""stderr to avoid write in html or xml file log message"""
sys.stderr.write(aStr + '\n')
try:
import unittestpy.HTMLTestRunner as HTST
except Exception:
HTST = None
errPrint("""
WARNING: no HTML output available.
try find 'test/unittestpy/HTMLTestRunner.py'.
""")
try:
import xmlrunner as XTST
except Exception:
XTST = None
errPrint("""
WARNING: no XML output available for unittest.
try 'pip install unittest-xml-reporting'.
""")
###################################################################
def locate(pattern, root=os.curdir):
"""
Locate all files matching supplied filename pattern in and below
supplied root directory.
"""
result = []
for path, dirs, files in os.walk(os.path.abspath(root)):
for filename in fnmatch.filter(files, pattern):
result.append( os.path.join(path, filename) )
return result
def printEnv(search=""):
"""
list all environment variables which name contains search string
example:
import AllTestLauncher as ATL
ATL.printEnv("ROOT_")
"""
env=os.environ
for i in sorted(env):
if search in i:
print(i)
def grepInEnv(search=""):
"""
list all environment variables which contains search string
example:
import AllTestLauncher as ATL
ATL.grepInEnv("XDATA")
"""
env=os.environ
for i in sorted(env):
done=False
for j in env[i].split(":"):
if search in j:
if not done:
print(i+" contains ")
done=True
print(" "+j)
def format_exception(msg, limit=None, trace=None):
"""
Format a stack trace and the exception information.
as traceback.format_exception(),
with all traceback only if user in ._developers
"""
etype, value, tb = sys.exc_info()
if _user in _developers:
res = "\n" + msg
if tb:
res += "\nTraceback (most recent call last):\n"
res += "".join(traceback.format_tb(tb, limit)) #[:-1])
res += "\n<"
res += "\n".join(traceback.format_exception_only(etype, value))
return res
else:
res = "\n" + msg
if tb:
res += "\nTraceback:\n"
res += "".join(traceback.format_tb(tb, limit)[-1:]) #[:-1])
res += "\n<"
res += "".join(traceback.format_exception_only(etype, value))
return res
###################################################################
def runOnArgs(args):
"""
launch tests on args.pattern files
"""
fromFileOrPath = args.rootPath
fileTestPattern = args.pattern
if fromFileOrPath == None:
directory, name = os.path.split( os.path.realpath( __file__ ) )
else:
if os.path.isdir(fromFileOrPath):
directory, name = (fromFileOrPath, None)
fileTestPatternCurrent = fileTestPattern
elif os.path.isfile(fromFileOrPath):
directory, name = os.path.split( os.path.realpath( fromFileOrPath ) )
fileTestPatternCurrent = name
else:
mess = "Cannot get file or directory '%s'" % fromFileOrPath
errPrint("ERROR: " + mess)
return None
#raise Exception("Cannot get file or directory '%s'" % fromFileOrPath)
#files = glob.glob(os.path.join(directory, "*Test.py"))
files = sorted(locate(fileTestPatternCurrent, directory))
filesForTest={}
for aFile in files:
aDir, aName = os.path.split(aFile)
aImport, ext = os.path.splitext(aName)
try:
if aFile in list(filesForTest.keys()):
print("WARNING: imported yet: "+aFile)
else:
sys.path.insert(0, aDir)
done = True
if verboseImport: errPrint("try import '%s'" % aImport)
aModule = __import__(aImport, globals(), locals(), [])
del sys.path[0]
done = False
filesForTest[aFile] = (aImport, aModule)
except Exception as e:
if done:
del sys.path[0] #attention of sys.path appends
done = False
msg = "ERROR: AllTestLauncher: import '%s':" % aFile
err = format_exception(msg)
errPrint(err)
continue
listfilesForTest = sorted(filesForTest.keys())
result = None
errPrint("AllTestLauncher test files:\n %s" % PP.pformat(listfilesForTest))
if len(listfilesForTest) == 0:
if debug: errPrint("WARNING: AllTestLauncher: empty list of test files")
return None
loader = unittest.TestLoader()
suite = None
for i,k in enumerate(listfilesForTest):
if debug: errPrint("Test: %s %s" % (i, k))
if i == 0:
suite = loader.loadTestsFromModule( filesForTest[k][1] )
pass
else:
suite.addTests( loader.loadTestsFromModule( filesForTest[k][1] ) )
pass
if args.type == "std":
runner = unittest.TextTestRunner(verbosity=args.verbosity)
elif args.type == "html":
runner = HTST.HTMLTestRunner(verbosity=args.verbosity, )
elif args.type == "xml":
if args.name == 'stdout':
#all-in-one xml output at 'sys.stdout' for pipe redirection
runner = XTST.XMLTestRunner(verbosity=args.verbosity, output=sys.stdout)
else:
#one file xml per test in suite in args.name directory
runner = XTST.XMLTestRunner(verbosity=args.verbosity, output=args.name)
else:
errPrint("ERROR: unknown type of output: '%s'" % args.type)
return None
if suite != None: result = runner.run(suite)
return result
###################################################################
def runFromEnvVar(envVar, fileTestPattern="*Test.py"):
"""
example:
import AllTestLauncher as ATL
ATL.runFromEnvVar("MICROGEN_ROOT_DIR")
ATL.runFromEnvVar("MICROGEN_ROOT_DIR", "aggregate_*GJKTest.py")
"""
env=os.environ
res = []
for i in sorted(env):
if envVar in i:
res.append(i)
if len(res) > 1:
mess = "multiple environment variable for '%s': %s" % (envVar, str(res))
errPrint("ERROR: " + mess)
return None
if len(res) < 1:
mess = "no environment variable for '%s'" % (envVar)
errPrint("ERROR: " + mess)
return None
res = res[0]
tmp = env[res].split(":")
if len(tmp) > 1:
mess = "need only one path in environment variable '%s'" % (res)
errPrint("ERROR: " + mess)
return None
run(fromFileOrPath=env[res], fileTestPattern=fileTestPattern)
###################################################################
def getParser():
parser = AP.ArgumentParser(description='launch All salomeTools python tests', argument_default=None)
parser.add_argument(
'-d', '--debug',
help='set debug mode, more verbose',
action='store_true',
)
parser.add_argument(
'-v', '--verbosity',
help='set verbosity of unittests [0|1|2...]',
default=2,
metavar='int'
)
parser.add_argument(
'-r', '--rootPath',
help="""\
dir name with absolute or relative path stand for root directory
of recursive searching unittest python files
""",
default=defaultdir,
metavar='dirPath'
)
parser.add_argument(
'-p', '--pattern',
help="file pattern for unittest files ['test_*.py'|'*Test.py'...]",
default="test_???_*.py", # as alphabetical ordered test site
metavar='filePattern'
)
parser.add_argument(
'-t', '--type',
help="type of output: ['std'(standart ascii)|'xml'|'html']",
default="std",
choices=['std', 'xml', 'html'],
metavar='outputType'
)
parser.add_argument(
'-n', '--name',
help="""\
(only for type xml)
name of directory output: ['test_reports'|...].
If name = 'stdout' then all-in-one xml output at 'sys.stdout'. For pipe redirection:
'>> AllTestLauncher.py -t xml -n stdout > tmp.xml'
""",
default="test_reports",
metavar='dirName'
)
return parser
#export PATH=defaultdir:${PATH}
###################################################################
if __name__ == '__main__':
# Make the src & command package accessible from all code
# as export PYTHONPATH=defaultdir:${PYTHONPATH}
# https://docs.python.org/2/library/os.html
# On some platforms, including FreeBSD and Mac OS X,
# setting environ may cause memory leak
# so use sys.path
# errPrint("INFO : AllTestLauncher sys.path:\n'%s'" % PP.pformat(sys.path)
if defaultdir not in sys.path[0]:
sys.path.insert(0, defaultdir)
errPrint("WARNING : sys.path prepend '%s'\n" % defaultdir)
args = getParser().parse_args(sys.argv[1:])
debug = args.debug
directory = os.path.realpath(args.rootPath)
if debug: print("INFO: args:\n %s" % PP.pformat(args))
sys.path.insert(0, directory) #supposed to be root of a package
runOnArgs(args)