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
67 # get path to origin sources
68 defaultdir = os.path.dirname(os.path.realpath(__file__))
69 # get path to salomeTools sources
71 srcdir = os.path.join(satdir, 'src')
72 cmdsdir = os.path.join(satdir, 'commands')
74 # Make the src & commands package accessible from all code
75 sys.path.insert(0, satdir)
76 sys.path.insert(0, srcdir) # TODO remove that
77 sys.path.insert(0, cmdsdir) # TODO remove that
79 _user = src.architecture.get_user()
80 # wambeke is christian at home
81 _developers = ["christian", "wambeke",] # ...who wants
84 """stderr to avoid write in html or xml file log message"""
85 sys.stderr.write(aStr + '\n')
88 import unittestpy.HTMLTestRunner as HTST
92 WARNING: no HTML output available.
93 try find 'test/unittestpy/HTMLTestRunner.py'.
98 import xmlrunner as XTST
102 WARNING: no XML output available for unittest.
103 try 'pip install unittest-xml-reporting'.
107 ###################################################################
108 def locate(pattern, root=os.curdir):
110 Locate all files matching supplied filename pattern in and below
111 supplied root directory.
114 for path, dirs, files in os.walk(os.path.abspath(root)):
115 for filename in fnmatch.filter(files, pattern):
116 result.append( os.path.join(path, filename) )
119 def printEnv(search=""):
121 list all environment variables which name contains search string
123 import AllTestLauncher as ATL
124 ATL.printEnv("ROOT_")
127 for i in sorted(env):
131 def grepInEnv(search=""):
133 list all environment variables which contains search string
135 import AllTestLauncher as ATL
136 ATL.grepInEnv("XDATA")
139 for i in sorted(env):
141 for j in env[i].split(":"):
144 print(i+" contains ")
148 def format_exception(msg, limit=None, trace=None):
150 Format a stack trace and the exception information.
151 as traceback.format_exception(),
152 with all traceback only if user in ._developers
154 etype, value, tb = sys.exc_info()
155 if _user in _developers:
158 res += "\nTraceback (most recent call last):\n"
159 res += "".join(traceback.format_tb(tb, limit)) #[:-1])
161 res += "\n".join(traceback.format_exception_only(etype, value))
166 res += "\nTraceback:\n"
167 res += "".join(traceback.format_tb(tb, limit)[-1:]) #[:-1])
169 res += "".join(traceback.format_exception_only(etype, value))
172 ###################################################################
175 launch tests on args.pattern files
177 fromFileOrPath = args.rootPath
178 fileTestPattern = args.pattern
179 if fromFileOrPath == None:
180 directory, name = os.path.split( os.path.realpath( __file__ ) )
182 if os.path.isdir(fromFileOrPath):
183 directory, name = (fromFileOrPath, None)
184 fileTestPatternCurrent = fileTestPattern
185 elif os.path.isfile(fromFileOrPath):
186 directory, name = os.path.split( os.path.realpath( fromFileOrPath ) )
187 fileTestPatternCurrent = name
189 mess = "Cannot get file or directory '%s'" % fromFileOrPath
190 errPrint("ERROR: " + mess)
192 #raise Exception("Cannot get file or directory '%s'" % fromFileOrPath)
194 #files = glob.glob(os.path.join(directory, "*Test.py"))
195 files = sorted(locate(fileTestPatternCurrent, directory))
200 aDir, aName = os.path.split(aFile)
201 aImport, ext = os.path.splitext(aName)
204 if aFile in list(filesForTest.keys()):
205 print("WARNING: imported yet: "+aFile)
207 sys.path.insert(0, aDir)
209 if verboseImport: errPrint("try import '%s'" % aImport)
210 aModule = __import__(aImport, globals(), locals(), [])
213 filesForTest[aFile] = (aImport, aModule)
214 except Exception as e:
216 del sys.path[0] #attention of sys.path appends
218 msg = "ERROR: AllTestLauncher: import '%s':" % aFile
219 err = format_exception(msg)
223 listfilesForTest = sorted(filesForTest.keys())
226 errPrint("AllTestLauncher test files:\n %s" % PP.pformat(listfilesForTest))
228 if len(listfilesForTest) == 0:
229 if debug: errPrint("WARNING: AllTestLauncher: empty list of test files")
232 loader = unittest.TestLoader()
235 for i,k in enumerate(listfilesForTest):
236 if debug: errPrint("Test: %s %s" % (i, k))
238 suite = loader.loadTestsFromModule( filesForTest[k][1] )
241 suite.addTests( loader.loadTestsFromModule( filesForTest[k][1] ) )
244 if args.type == "std":
245 runner = unittest.TextTestRunner(verbosity=args.verbosity)
246 elif args.type == "html":
247 runner = HTST.HTMLTestRunner(verbosity=args.verbosity, )
248 elif args.type == "xml":
249 if args.name == 'stdout':
250 #all-in-one xml output at 'sys.stdout' for pipe redirection
251 runner = XTST.XMLTestRunner(verbosity=args.verbosity, output=sys.stdout)
253 #one file xml per test in suite in args.name directory
254 runner = XTST.XMLTestRunner(verbosity=args.verbosity, output=args.name)
256 errPrint("ERROR: unknown type of output: '%s'" % args.type)
259 if suite != None: result = runner.run(suite)
262 ###################################################################
263 def runFromEnvVar(envVar, fileTestPattern="*Test.py"):
266 import AllTestLauncher as ATL
267 ATL.runFromEnvVar("MICROGEN_ROOT_DIR")
268 ATL.runFromEnvVar("MICROGEN_ROOT_DIR", "aggregate_*GJKTest.py")
272 for i in sorted(env):
276 mess = "multiple environment variable for '%s': %s" % (envVar, str(res))
277 errPrint("ERROR: " + mess)
280 mess = "no environment variable for '%s'" % (envVar)
281 errPrint("ERROR: " + mess)
284 tmp = env[res].split(":")
286 mess = "need only one path in environment variable '%s'" % (res)
287 errPrint("ERROR: " + mess)
289 run(fromFileOrPath=env[res], fileTestPattern=fileTestPattern)
292 ###################################################################
294 parser = AP.ArgumentParser(description='launch All salomeTools python tests', argument_default=None)
298 help='set debug mode, more verbose',
303 help='set verbosity of unittests [0|1|2...]',
310 dir name with absolute or relative path stand for root directory
311 of recursive searching unittest python files
318 help="file pattern for unittest files ['test_*.py'|'*Test.py'...]",
319 default="test_???_*.py", # as alphabetical ordered test site
320 metavar='filePattern'
324 help="type of output: ['std'(standart ascii)|'xml'|'html']",
326 choices=['std', 'xml', 'html'],
333 name of directory output: ['test_reports'|...].
334 If name = 'stdout' then all-in-one xml output at 'sys.stdout'. For pipe redirection:
335 '>> AllTestLauncher.py -t xml -n stdout > tmp.xml'
337 default="test_reports",
342 #export PATH=defaultdir:${PATH}
344 ###################################################################
345 if __name__ == '__main__':
346 # Make the src & command package accessible from all code
347 # as export PYTHONPATH=defaultdir:${PYTHONPATH}
348 # https://docs.python.org/2/library/os.html
349 # On some platforms, including FreeBSD and Mac OS X,
350 # setting environ may cause memory leak
352 # errPrint("INFO : AllTestLauncher sys.path:\n'%s'" % PP.pformat(sys.path)
353 if defaultdir not in sys.path[0]:
354 sys.path.insert(0, defaultdir)
355 errPrint("WARNING : sys.path prepend '%s'\n" % defaultdir)
357 args = getParser().parse_args(sys.argv[1:])
359 directory = os.path.realpath(args.rootPath)
360 if debug: print("INFO: args:\n %s" % PP.pformat(args))
361 sys.path.insert(0, directory) #supposed to be root of a package