testall.py
6.4 KB
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
import sys, os
import re
import unittest
import traceback
import pywin32_testutil
# A list of demos that depend on user-interface of *any* kind. Tests listed
# here are not suitable for unattended testing.
ui_demos = """GetSaveFileName print_desktop win32cred_demo win32gui_demo
win32gui_dialog win32gui_menu win32gui_taskbar
win32rcparser_demo winprocess win32console_demo
win32clipboard_bitmapdemo
win32gui_devicenotify
NetValidatePasswordPolicy""".split()
# Other demos known as 'bad' (or at least highly unlikely to work)
# cerapi: no CE module is built (CE via pywin32 appears dead)
# desktopmanager: hangs (well, hangs for 60secs or so...)
# EvtSubscribe_*: must be run together
bad_demos = """cerapi desktopmanager win32comport_demo
EvtSubscribe_pull EvtSubscribe_push
""".split()
argvs = {
"rastest": ("-l",),
}
no_user_interaction = False
# re to pull apart an exception line into the exception type and the args.
re_exception = re.compile("([a-zA-Z0-9_.]*): (.*)$")
def find_exception_in_output(data):
have_traceback = False
for line in data.splitlines():
line = line.decode('ascii') # not sure what the correct encoding is...
if line.startswith("Traceback ("):
have_traceback = True
continue
if line.startswith(" "):
continue
if have_traceback:
# first line not starting with a space since the traceback.
# must be the exception!
m = re_exception.match(line)
if m:
exc_type, args = m.groups()
# get hacky - get the *real* exception object from the name.
bits = exc_type.split(".", 1)
if len(bits) > 1:
mod = __import__(bits[0])
exc = getattr(mod, bits[1])
else:
# probably builtin
exc = eval(bits[0])
else:
# hrm - probably just an exception with no args
try:
exc = eval(line.strip())
args = "()"
except:
return None
# try and turn the args into real args.
try:
args = eval(args)
except:
pass
if not isinstance(args, tuple):
args = (args,)
# try and instantiate the exception.
try:
ret = exc(*args)
except:
ret = None
return ret
# apparently not - keep looking...
have_traceback = False
class TestRunner:
def __init__(self, argv):
self.argv = argv
self.__name__ = "Test Runner for cmdline {}".format(argv)
def __call__(self):
import subprocess
p = subprocess.Popen(self.argv,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output, _ = p.communicate()
rc = p.returncode
if rc:
base = os.path.basename(self.argv[1])
# See if we can detect and reconstruct an exception in the output.
reconstituted = find_exception_in_output(output)
if reconstituted is not None:
raise reconstituted
raise AssertionError("%s failed with exit code %s. Output is:\n%s" % (base, rc, output))
def get_demo_tests():
import win32api
ret = []
demo_dir = os.path.abspath(os.path.join(os.path.dirname(win32api.__file__), "Demos"))
assert os.path.isdir(demo_dir), demo_dir
for name in os.listdir(demo_dir):
base, ext = os.path.splitext(name)
if base in ui_demos and no_user_interaction:
continue
# Skip any other files than .py and bad tests in any case
if ext != ".py" or base in bad_demos:
continue
argv = (sys.executable, os.path.join(demo_dir, base+".py")) + \
argvs.get(base, ())
ret.append(unittest.FunctionTestCase(TestRunner(argv), description="win32/demos/" + name))
return ret
def import_all():
# Some hacks for import order - dde depends on win32ui
try:
import win32ui
except ImportError:
pass # 'what-ev-a....'
import win32api
dir = os.path.dirname(win32api.__file__)
num = 0
is_debug = os.path.basename(win32api.__file__).endswith("_d")
for name in os.listdir(dir):
base, ext = os.path.splitext(name)
if (ext==".pyd") and \
name != "_winxptheme.pyd" and \
(is_debug and base.endswith("_d") or \
not is_debug and not base.endswith("_d")):
try:
__import__(base)
except:
print(("FAILED to import", name))
raise
num += 1
def suite():
# Loop over all .py files here, except me :)
try:
me = __file__
except NameError:
me = sys.argv[0]
me = os.path.abspath(me)
files = os.listdir(os.path.dirname(me))
suite = unittest.TestSuite()
suite.addTest(unittest.FunctionTestCase(import_all))
for file in files:
base, ext = os.path.splitext(file)
if ext=='.py' and os.path.basename(me) != file:
try:
mod = __import__(base)
except:
print("FAILED to import test module %r" % base)
traceback.print_exc()
continue
if hasattr(mod, "suite"):
test = mod.suite()
else:
test = unittest.defaultTestLoader.loadTestsFromModule(mod)
suite.addTest(test)
for test in get_demo_tests():
suite.addTest(test)
return suite
class CustomLoader(pywin32_testutil.TestLoader):
def loadTestsFromModule(self, module):
return self.fixupTestsForLeakTests(suite())
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description="Test runner for PyWin32/win32")
parser.add_argument("-no-user-interaction",
default=no_user_interaction,
action='store_true',
help="Run all tests without user interaction")
parsed_args, remains = parser.parse_known_args()
no_user_interaction = parsed_args.no_user_interaction
sys.argv = [sys.argv[0]] + remains
pywin32_testutil.testmain(testLoader=CustomLoader())