2 # -*- coding: utf-8 -*-
4 # Copyright (C) 2008-2018 CEA/DEN
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 # See http://www.salome-platform.org or email : webmaster.salome@opencascade.com
24 Test all SAT unittest files (test*.py) existing in subdirectories of a root directory
27 | >> AllTestLauncherSat.py --rootPath='.' --pattern='test_???_*.py'
31 #### base of algorithm functionality
33 #see http://www.voidspace.org.uk/python/articles/introduction-to-unittest.shtml
38 import test_something2
39 import test_something3
41 loader = unittest.TestLoader()
43 suite = loader.loadTestsFromModule(test_something)
44 suite.addTests(loader.loadTestsFromModule(test_something2))
45 suite.addTests(loader.loadTestsFromModule(test_something3))
47 runner = unittest.TextTestRunner(verbosity=2)
48 result = runner.run(suite)
60 import pprint as PP #pretty print
66 # get path to origin sources
67 defaultdir = os.path.dirname(os.path.realpath(__file__))
68 # get path to salomeTools sources
70 srcdir = os.path.join(satdir, 'src')
71 cmdsdir = os.path.join(satdir, 'commands')
73 # Make the src & commands package accessible from all code
74 sys.path.insert(0, satdir)
75 sys.path.insert(0, srcdir) # TODO remove that
76 sys.path.insert(0, cmdsdir) # TODO remove that
78 _user = os.environ['USER']
79 # wambeke is christian at home
80 _developers = ["christian", "wambeke",] # ...who wants
83 """stderr to avoid write in html or xml file log message"""
84 sys.stderr.write(aStr + '\n')
87 import unittestpy.HTMLTestRunner as HTST
91 WARNING: no HTML output available.
92 try find 'test/unittestpy/HTMLTestRunner.py'.
97 import xmlrunner as XTST
101 WARNING: no XML output available for unittest.
102 try 'pip install unittest-xml-reporting'.
106 ###################################################################
107 def locate(pattern, root=os.curdir):
109 Locate all files matching supplied filename pattern in and below
110 supplied root directory.
113 for path, dirs, files in os.walk(os.path.abspath(root)):
114 for filename in fnmatch.filter(files, pattern):
115 result.append( os.path.join(path, filename) )
118 def printEnv(search=""):
120 list all environment variables which name contains search string
122 import AllTestLauncher as ATL
123 ATL.printEnv("ROOT_")
126 for i in sorted(env):
130 def grepInEnv(search=""):
132 list all environment variables which contains search string
134 import AllTestLauncher as ATL
135 ATL.grepInEnv("XDATA")
138 for i in sorted(env):
140 for j in env[i].split(":"):
143 print(i+" contains ")
147 def format_exception(msg, limit=None, trace=None):
149 Format a stack trace and the exception information.
150 as traceback.format_exception(),
151 with all traceback only if user in ._developers
153 etype, value, tb = sys.exc_info()
154 if _user in _developers:
157 res += "\nTraceback (most recent call last):\n"
158 res += "".join(traceback.format_tb(tb, limit)) #[:-1])
160 res += "\n".join(traceback.format_exception_only(etype, value))
165 res += "\nTraceback:\n"
166 res += "".join(traceback.format_tb(tb, limit)[-1:]) #[:-1])
168 res += "".join(traceback.format_exception_only(etype, value))
171 ###################################################################
174 launch tests on args.pattern files
176 fromFileOrPath = args.rootPath
177 fileTestPattern = args.pattern
178 if fromFileOrPath == None:
179 directory, name = os.path.split( os.path.realpath( __file__ ) )
181 if os.path.isdir(fromFileOrPath):
182 directory, name = (fromFileOrPath, None)
183 fileTestPatternCurrent = fileTestPattern
184 elif os.path.isfile(fromFileOrPath):
185 directory, name = os.path.split( os.path.realpath( fromFileOrPath ) )
186 fileTestPatternCurrent = name
188 mess = "Cannot get file or directory '%s'" % fromFileOrPath
189 errPrint("ERROR: " + mess)
191 #raise Exception("Cannot get file or directory '%s'" % fromFileOrPath)
193 #files = glob.glob(os.path.join(directory, "*Test.py"))
194 files = sorted(locate(fileTestPatternCurrent, directory))
199 aDir, aName = os.path.split(aFile)
200 aImport, ext = os.path.splitext(aName)
203 if aFile in list(filesForTest.keys()):
204 print("WARNING: imported yet: "+aFile)
206 sys.path.insert(0, aDir)
208 if verboseImport: errPrint("try import '%s'" % aImport)
209 aModule = __import__(aImport, globals(), locals(), [])
212 filesForTest[aFile] = (aImport, aModule)
213 except Exception as e:
215 del sys.path[0] #attention of sys.path appends
217 msg = "ERROR: AllTestLauncher: import '%s':" % aFile
218 err = format_exception(msg)
222 listfilesForTest = sorted(filesForTest.keys())
225 errPrint("AllTestLauncher test files:\n %s" % PP.pformat(listfilesForTest))
227 if len(listfilesForTest) == 0:
228 if debug: errPrint("WARNING: AllTestLauncher: empty list of test files")
231 loader = unittest.TestLoader()
234 for i,k in enumerate(listfilesForTest):
235 if debug: errPrint("Test: %s %s" % (i, k))
237 suite = loader.loadTestsFromModule( filesForTest[k][1] )
240 suite.addTests( loader.loadTestsFromModule( filesForTest[k][1] ) )
243 if args.type == "std":
244 runner = unittest.TextTestRunner(verbosity=args.verbosity)
245 elif args.type == "html":
246 runner = HTST.HTMLTestRunner(verbosity=args.verbosity, )
247 elif args.type == "xml":
248 if args.name == 'stdout':
249 #all-in-one xml output at 'sys.stdout' for pipe redirection
250 runner = XTST.XMLTestRunner(verbosity=args.verbosity, output=sys.stdout)
252 #one file xml per test in suite in args.name directory
253 runner = XTST.XMLTestRunner(verbosity=args.verbosity, output=args.name)
255 errPrint("ERROR: unknown type of output: '%s'" % args.type)
258 if suite != None: result = runner.run(suite)
261 ###################################################################
262 def runFromEnvVar(envVar, fileTestPattern="*Test.py"):
265 import AllTestLauncher as ATL
266 ATL.runFromEnvVar("MICROGEN_ROOT_DIR")
267 ATL.runFromEnvVar("MICROGEN_ROOT_DIR", "aggregate_*GJKTest.py")
271 for i in sorted(env):
275 mess = "multiple environment variable for '%s': %s" % (envVar, str(res))
276 errPrint("ERROR: " + mess)
279 mess = "no environment variable for '%s'" % (envVar)
280 errPrint("ERROR: " + mess)
283 tmp = env[res].split(":")
285 mess = "need only one path in environment variable '%s'" % (res)
286 errPrint("ERROR: " + mess)
288 run(fromFileOrPath=env[res], fileTestPattern=fileTestPattern)
291 ###################################################################
293 parser = AP.ArgumentParser(description='launch All salomeTools python tests', argument_default=None)
297 help='set debug mode, more verbose',
302 help='set verbosity of unittests [0|1|2...]',
309 dir name with absolute or relative path stand for root directory
310 of recursive searching unittest python files
317 help="file pattern for unittest files ['test_*.py'|'*Test.py'...]",
318 default="test_???_*.py", # as alphabetical ordered test site
319 metavar='filePattern'
323 help="type of output: ['std'(standart ascii)|'xml'|'html']",
325 choices=['std', 'xml', 'html'],
332 name of directory output: ['test_reports'|...].
333 If name = 'stdout' then all-in-one xml output at 'sys.stdout'. For pipe redirection:
334 '>> AllTestLauncher.py -t xml -n stdout > tmp.xml'
336 default="test_reports",
341 #export PATH=defaultdir:${PATH}
343 ###################################################################
344 if __name__ == '__main__':
345 # Make the src & command package accessible from all code
346 # as export PYTHONPATH=defaultdir:${PYTHONPATH}
347 # https://docs.python.org/2/library/os.html
348 # On some platforms, including FreeBSD and Mac OS X,
349 # setting environ may cause memory leak
351 # errPrint("INFO : AllTestLauncher sys.path:\n'%s'" % PP.pformat(sys.path)
352 if defaultdir not in sys.path[0]:
353 sys.path.insert(0, defaultdir)
354 errPrint("WARNING : sys.path prepend '%s'\n" % defaultdir)
356 args = getParser().parse_args(sys.argv[1:])
358 directory = os.path.realpath(args.rootPath)
359 if debug: print("INFO: args:\n %s" % PP.pformat(args))
360 sys.path.insert(0, directory) #supposed to be root of a package