Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

testall.py 7.1KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import os
  2. import re
  3. import sys
  4. import traceback
  5. import unittest
  6. import pywin32_testutil
  7. # A list of demos that depend on user-interface of *any* kind. Tests listed
  8. # here are not suitable for unattended testing.
  9. ui_demos = """GetSaveFileName print_desktop win32cred_demo win32gui_demo
  10. win32gui_dialog win32gui_menu win32gui_taskbar
  11. win32rcparser_demo winprocess win32console_demo
  12. win32clipboard_bitmapdemo
  13. win32gui_devicenotify
  14. NetValidatePasswordPolicy""".split()
  15. # Other demos known as 'bad' (or at least highly unlikely to work)
  16. # cerapi: no CE module is built (CE via pywin32 appears dead)
  17. # desktopmanager: hangs (well, hangs for 60secs or so...)
  18. # EvtSubscribe_*: must be run together:
  19. # SystemParametersInfo: a couple of the params cause markh to hang, and there's
  20. # no great reason to adjust (twice!) all those system settings!
  21. bad_demos = """cerapi desktopmanager win32comport_demo
  22. EvtSubscribe_pull EvtSubscribe_push
  23. SystemParametersInfo
  24. """.split()
  25. argvs = {
  26. "rastest": ("-l",),
  27. }
  28. no_user_interaction = True
  29. # re to pull apart an exception line into the exception type and the args.
  30. re_exception = re.compile("([a-zA-Z0-9_.]*): (.*)$")
  31. def find_exception_in_output(data):
  32. have_traceback = False
  33. for line in data.splitlines():
  34. line = line.decode("ascii") # not sure what the correct encoding is...
  35. if line.startswith("Traceback ("):
  36. have_traceback = True
  37. continue
  38. if line.startswith(" "):
  39. continue
  40. if have_traceback:
  41. # first line not starting with a space since the traceback.
  42. # must be the exception!
  43. m = re_exception.match(line)
  44. if m:
  45. exc_type, args = m.groups()
  46. # get hacky - get the *real* exception object from the name.
  47. bits = exc_type.split(".", 1)
  48. if len(bits) > 1:
  49. mod = __import__(bits[0])
  50. exc = getattr(mod, bits[1])
  51. else:
  52. # probably builtin
  53. exc = eval(bits[0])
  54. else:
  55. # hrm - probably just an exception with no args
  56. try:
  57. exc = eval(line.strip())
  58. args = "()"
  59. except:
  60. return None
  61. # try and turn the args into real args.
  62. try:
  63. args = eval(args)
  64. except:
  65. pass
  66. if not isinstance(args, tuple):
  67. args = (args,)
  68. # try and instantiate the exception.
  69. try:
  70. ret = exc(*args)
  71. except:
  72. ret = None
  73. return ret
  74. # apparently not - keep looking...
  75. have_traceback = False
  76. class TestRunner:
  77. def __init__(self, argv):
  78. self.argv = argv
  79. self.__name__ = "Test Runner for cmdline {}".format(argv)
  80. def __call__(self):
  81. import subprocess
  82. p = subprocess.Popen(
  83. self.argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
  84. )
  85. output, _ = p.communicate()
  86. rc = p.returncode
  87. if rc:
  88. base = os.path.basename(self.argv[1])
  89. # See if we can detect and reconstruct an exception in the output.
  90. reconstituted = find_exception_in_output(output)
  91. if reconstituted is not None:
  92. raise reconstituted
  93. raise AssertionError(
  94. "%s failed with exit code %s. Output is:\n%s" % (base, rc, output)
  95. )
  96. def get_demo_tests():
  97. import win32api
  98. ret = []
  99. demo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Demos"))
  100. assert os.path.isdir(demo_dir), demo_dir
  101. for name in os.listdir(demo_dir):
  102. base, ext = os.path.splitext(name)
  103. if base in ui_demos and no_user_interaction:
  104. continue
  105. # Skip any other files than .py and bad tests in any case
  106. if ext != ".py" or base in bad_demos:
  107. continue
  108. argv = (sys.executable, os.path.join(demo_dir, base + ".py")) + argvs.get(
  109. base, ()
  110. )
  111. ret.append(
  112. unittest.FunctionTestCase(
  113. TestRunner(argv), description="win32/demos/" + name
  114. )
  115. )
  116. return ret
  117. def import_all():
  118. # Some hacks for import order - dde depends on win32ui
  119. try:
  120. import win32ui
  121. except ImportError:
  122. pass # 'what-ev-a....'
  123. import win32api
  124. dir = os.path.dirname(win32api.__file__)
  125. num = 0
  126. is_debug = os.path.basename(win32api.__file__).endswith("_d")
  127. for name in os.listdir(dir):
  128. base, ext = os.path.splitext(name)
  129. # handle `modname.cp310-win_amd64.pyd` etc
  130. base = base.split(".")[0]
  131. if (
  132. (ext == ".pyd")
  133. and name != "_winxptheme.pyd"
  134. and (
  135. is_debug
  136. and base.endswith("_d")
  137. or not is_debug
  138. and not base.endswith("_d")
  139. )
  140. ):
  141. try:
  142. __import__(base)
  143. except:
  144. print("FAILED to import", name)
  145. raise
  146. num += 1
  147. def suite():
  148. # Loop over all .py files here, except me :)
  149. try:
  150. me = __file__
  151. except NameError:
  152. me = sys.argv[0]
  153. me = os.path.abspath(me)
  154. files = os.listdir(os.path.dirname(me))
  155. suite = unittest.TestSuite()
  156. suite.addTest(unittest.FunctionTestCase(import_all))
  157. for file in files:
  158. base, ext = os.path.splitext(file)
  159. if ext == ".py" and os.path.basename(me) != file:
  160. try:
  161. mod = __import__(base)
  162. except:
  163. print("FAILED to import test module %r" % base)
  164. traceback.print_exc()
  165. continue
  166. if hasattr(mod, "suite"):
  167. test = mod.suite()
  168. else:
  169. test = unittest.defaultTestLoader.loadTestsFromModule(mod)
  170. suite.addTest(test)
  171. for test in get_demo_tests():
  172. suite.addTest(test)
  173. return suite
  174. class CustomLoader(pywin32_testutil.TestLoader):
  175. def loadTestsFromModule(self, module):
  176. return self.fixupTestsForLeakTests(suite())
  177. if __name__ == "__main__":
  178. import argparse
  179. parser = argparse.ArgumentParser(description="Test runner for PyWin32/win32")
  180. parser.add_argument(
  181. "-no-user-interaction",
  182. default=False,
  183. action="store_true",
  184. help="(This is now the default - use `-user-interaction` to include them)",
  185. )
  186. parser.add_argument(
  187. "-user-interaction",
  188. action="store_true",
  189. help="Include tests which require user interaction",
  190. )
  191. parsed_args, remains = parser.parse_known_args()
  192. if parsed_args.no_user_interaction:
  193. print(
  194. "Note: -no-user-interaction is now the default, run with `-user-interaction` to include them."
  195. )
  196. no_user_interaction = not parsed_args.user_interaction
  197. sys.argv = [sys.argv[0]] + remains
  198. pywin32_testutil.testmain(testLoader=CustomLoader())