-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_all.py
More file actions
155 lines (137 loc) · 5.38 KB
/
Copy pathtest_all.py
File metadata and controls
155 lines (137 loc) · 5.38 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
#!/usr/bin/env python3
"""Run all the chapter modules, doctests or performance() function
This is run from the top-level directory, where all of the sample
data files are also located.
When runnning individual examples, working directory is expected
to be this top-level directory.
"""
import doctest
import runpy
import unittest
import sys
import time
from enum import Enum
import importlib
from pathlib import Path
from typing import Any, Iterator, Tuple, Iterable
import pytest
DEBUG = False # Can't easily use logging -- can conflict with chapters on logging.
DOCTEST_EXCLUDE = {
'ch13_ex4' # Requires a separate server to be started, too complex for this script
}
def package_module_iter(packages: Iterable[Path]) -> Iterator[Tuple[Path, Iterator[Path]]]:
"""For a given list of packages, emit the package name and a generator
for all modules in the package. Structured like ``itertools.groupby()``.
With a filter to reject caches of various kinds.
keep = lambda path: not all(
[filename.stem.startswith("__"), filename.stem.endswith("__"), filename.suffix == ".py"]
)
yield package, filter(keep, package.glob("*.py"))
"""
def module_iter(package: Path, module_iter: Iterable[Path]) -> Iterator[Path]:
"""
A filter to reject __init__.py and similar names.
"""
if DEBUG:
print(f"Package {package}")
for filename in module_iter:
if (
filename.stem.startswith("__")
and filename.stem.endswith("__")
and filename.suffix == ".py"
):
continue
if DEBUG:
print(f" file {filename.name} module {filename.stem}")
yield filename
for package in packages:
yield (package,
module_iter(package, package.glob("*.py")))
def run(pkg_mod_iter: Iterable[Tuple[Path, Iterable[Path]]]) -> None:
"""Run each module, with a few exclusions."""
for package, module_iter in pkg_mod_iter:
print()
print(package.name)
print("="*len(package.name))
print()
for module in module_iter:
if module.stem in DOCTEST_EXCLUDE:
print(f"Excluding {module}")
continue
status = runpy.run_path(module, run_name="__main__")
if status != 0:
sys.exit(f"Failure: {module}")
import subprocess
def run_doctest_suite(pkg_mod_iter: Iterable[Tuple[Path, Iterable[Path]]]) -> None:
"""Doctest each module individually. With a few exclusions.
Might be simpler to use doctest.testfile()? However, the examples aren't laid out for this.
"""
for package, module_iter in pkg_mod_iter:
print()
print(package.name)
print("="*len(package.name))
print()
for module_path in module_iter:
if module_path.stem in DOCTEST_EXCLUDE:
print(f"Excluding {module_path}")
continue
result = subprocess.run(['python3', '-m', 'doctest', str(module_path)])
if result.returncode != 0:
sys.exit(f"Failure {result!r} in {module_path}")
class PytestExit(int, Enum):
Success = 0
Failures = 1
Interrupted = 2
InternalError = 3
CommandLineError = 4
NoTests = 5
def run_pytest_suite(pkg_mod_iter: Iterable[Tuple[Path, Iterable[Path]]]) -> None:
"""Pytest each module's modules.
"""
for package, module_iter in pkg_mod_iter:
print()
print(package.name)
print("="*len(package.name))
print()
names = [f"{m.parent.name}/{m.name}" for m in (module_iter)]
print(names)
status = pytest.main(names)
if status not in (PytestExit.Success, PytestExit.NoTests):
sys.exit(f"Failure {PytestExit(status)!r} in {names}")
def run_performance(pkg_mod_iter: Iterable[Tuple[Path, Iterable[Path]]]) -> None:
"""Locate a performance() function in each module and run it."""
for package, module_iter in pkg_mod_iter:
print()
print(package.name)
print("="*len(package.name))
print()
for module in module_iter:
print(module)
try:
imported_module = __import__(
f"{package.name}.{module.stem}", fromlist=[module.stem, "performance"])
imported_module.performance()
except AttributeError:
pass # no performance() function in the module.
def master_test_suite(pkg_mod_iter: Iterable[Tuple[Path, Iterable[Path]]]) -> None:
"""Deprecated. Use pytest, instead.
Build a master unittest test suite from all modules and run that.
"""
master_suite = unittest.TestSuite()
for package, module_iter in pkg_mod_iter:
for module in module_iter:
print(f"{package.name}.{module.stem}", file=sys.stderr)
suite = doctest.DocTestSuite(f"{package.name}.{module.stem}")
print(" ", suite, file=sys.stderr)
master_suite.addTests(suite)
runner = unittest.TextTestRunner(verbosity=1)
runner.run(master_suite)
def chap_key(name: Path) -> int:
_, _, n = name.stem.partition("_")
return int(n)
if __name__ == "__main__":
content = sorted(Path.cwd().glob("Chapter_*"), key=chap_key)
if DEBUG:
print(content, file=sys.stderr)
run_doctest_suite(package_module_iter(content))
run_pytest_suite(package_module_iter(content))