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
|
#!/bin/sh
''''exec python3 -u "$0" "$@" #'''
# $Id$
# Author: David Goodger <goodger@python.org>,
# Garth Kidd <garth@deadlybloodyserious.com>
# Copyright: This module has been placed in the public domain.
__doc__ = """\
All modules named 'test_*.py' in the current directory, and recursively in
subdirectories (packages) called 'test_*', are loaded and test suites within
are run.
"""
import time
# Start point for actual elapsed time, including imports
# and setup outside of unittest.
start = time.time()
import atexit # noqa: E402
import glob # noqa: E402
import importlib # noqa: E402
import os # noqa: E402
from pathlib import Path # noqa: E402
import platform # noqa: E402
import sys # noqa: E402
# Prepend the "docutils root" to the Python library path
# so we import the local `docutils` package.
# For Python < 3.9, we need `resolve()` to ensure an absolute path.
# https://docs.python.org/3/whatsnew/3.9.html#other-language-changes
DOCUTILS_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(DOCUTILS_ROOT))
import docutils # noqa: E402
class Tee:
"""Write to a file and a stream (default: stdout) simultaneously."""
def __init__(self, filename, stream=sys.__stdout__):
self.file = open(filename, 'w', encoding='utf-8',
errors='backslashreplace')
atexit.register(self.close)
self.stream = stream
self.encoding = getattr(stream, 'encoding', None)
def close(self):
self.file.close()
self.file = None
def write(self, string):
try:
self.stream.write(string)
except UnicodeEncodeError:
bstring = string.encode(self.encoding, errors='backslashreplace')
self.stream.write(bstring.decode())
if self.file:
self.file.write(string)
def flush(self):
self.stream.flush()
if self.file:
self.file.flush()
# must redirect stderr *before* first import of unittest
sys.stdout = sys.stderr = Tee('alltests.out')
import unittest # NoQA: E402
def loadTestModules(path):
"""
Return a test suite composed of all the tests from modules in a directory.
Search for modules in directory `path`, beginning with `name`.
Then search subdirectories (also beginning with `name`)
recursively. Subdirectories must be Python packages; they must contain an
'__init__.py' module.
"""
testLoader = unittest.defaultTestLoader
testSuite = unittest.TestSuite()
testModules = []
path = os.path.abspath(path) # current working dir if `path` empty
paths = [path]
while paths:
p = paths.pop() + '/test_'
for file_path in glob.glob(p + '*.py'):
testModules.append(path2mod(os.path.relpath(file_path, path)))
for file_path in glob.glob(p + '*/__init__.py'):
paths.append(os.path.dirname(file_path))
# Import modules and add their tests to the suite.
sys.path.insert(0, path)
for mod in testModules:
try:
module = importlib.import_module(mod)
except ImportError:
print(f"ERROR: Can't import {mod}, skipping its tests:",
file=sys.stderr)
sys.excepthook(*sys.exc_info())
else:
# if there's a suite defined, incorporate its contents
try:
suite = module.suite
except AttributeError:
# Look for individual tests
moduleTests = testLoader.loadTestsFromModule(module)
# unittest.TestSuite.addTests() doesn't work as advertised,
# as it can't load tests from another TestSuite, so we have
# to cheat:
testSuite.addTest(moduleTests)
else:
if not callable(suite):
raise AssertionError(f"don't understand suite ({mod})")
testSuite.addTest(suite())
sys.path.pop(0)
return testSuite
def path2mod(path):
"""Convert a file path to a dotted module name."""
return path[:-3].replace(os.sep, '.')
class NumbersTestResult(unittest.TextTestResult):
"""Result class that counts subTests."""
def addSubTest(self, test, subtest, error):
super().addSubTest(test, subtest, error)
self.testsRun += 1
if self.dots:
self.stream.write('.' if error is None else 'E')
self.stream.flush()
if __name__ == '__main__':
suite = loadTestModules(DOCUTILS_ROOT/'test')
print(f'Testing Docutils {docutils.__version__} '
f'with Python {sys.version.split()[0]} '
f'on {time.strftime("%Y-%m-%d at %H:%M:%S")}')
print(f'OS: {platform.system()} {platform.release()} {platform.version()} '
f'({sys.platform}, {platform.platform()})')
print(f'Working directory: {os.getcwd()}')
print(f'Docutils package: {os.path.dirname(docutils.__file__)}')
sys.stdout.flush()
result = unittest.TextTestRunner(resultclass=NumbersTestResult).run(suite)
finish = time.time()
print(f'Elapsed time: {finish - start:.3f} seconds')
sys.exit(not result.wasSuccessful())
|