-
-
Notifications
You must be signed in to change notification settings - Fork 538
/
Copy pathmaxi_cov.py
executable file
·167 lines (142 loc) · 5 KB
/
maxi_cov.py
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
#!/usr/bin/env python
"""Measure coverage of each module by its test module."""
import glob
import os.path
import subprocess
import sys
UNMAPPED_SRC_FILES = [
"websockets/typing.py",
"websockets/version.py",
]
UNMAPPED_TEST_FILES = [
"tests/test_exports.py",
]
def check_environment():
"""Check that prerequisites for running this script are met."""
try:
import websockets # noqa: F401
except ImportError:
print("failed to import websockets; is src on PYTHONPATH?")
return False
try:
import coverage # noqa: F401
except ImportError:
print("failed to locate Coverage.py; is it installed?")
return False
return True
def get_mapping(src_dir="src"):
"""Return a dict mapping each source file to its test file."""
# List source and test files.
src_files = glob.glob(
os.path.join(src_dir, "websockets/**/*.py"),
recursive=True,
)
test_files = glob.glob(
"tests/**/*.py",
recursive=True,
)
src_files = [
os.path.relpath(src_file, src_dir)
for src_file in sorted(src_files)
if "legacy" not in os.path.dirname(src_file)
and os.path.basename(src_file) != "__init__.py"
and os.path.basename(src_file) != "__main__.py"
and os.path.basename(src_file) != "async_timeout.py"
and os.path.basename(src_file) != "compatibility.py"
]
test_files = [
test_file
for test_file in sorted(test_files)
if "legacy" not in os.path.dirname(test_file)
and os.path.basename(test_file) != "__init__.py"
and os.path.basename(test_file).startswith("test_")
]
# Map source files to test files.
mapping = {}
unmapped_test_files = set()
for test_file in test_files:
dir_name, file_name = os.path.split(test_file)
assert dir_name.startswith("tests")
assert file_name.startswith("test_")
src_file = os.path.join(
"websockets" + dir_name[len("tests") :],
file_name[len("test_") :],
)
if src_file in src_files:
mapping[src_file] = test_file
else:
unmapped_test_files.add(test_file)
unmapped_src_files = set(src_files) - set(mapping)
# Ensure that all files are mapped.
assert unmapped_src_files == set(UNMAPPED_SRC_FILES)
assert unmapped_test_files == set(UNMAPPED_TEST_FILES)
return mapping
def get_ignored_files(src_dir="src"):
"""Return the list of files to exclude from coverage measurement."""
# */websockets matches src/websockets and .tox/**/site-packages/websockets.
return [
# There are no tests for the __main__ module.
"*/websockets/__main__.py",
# There is nothing to test on type declarations.
"*/websockets/typing.py",
# We don't test compatibility modules with previous versions of Python
# or websockets (import locations).
"*/websockets/asyncio/async_timeout.py",
"*/websockets/asyncio/compatibility.py",
# This approach isn't applicable to the test suite of the legacy
# implementation, due to the huge test_client_server test module.
"*/websockets/legacy/*",
"tests/legacy/*",
] + [
# Exclude test utilities that are shared between several test modules.
# Also excludes this script.
test_file
for test_file in sorted(glob.glob("tests/**/*.py", recursive=True))
if "legacy" not in os.path.dirname(test_file)
and os.path.basename(test_file) != "__init__.py"
and not os.path.basename(test_file).startswith("test_")
]
def run_coverage(mapping, src_dir="src"):
# Initialize a new coverage measurement session. The --source option
# includes all files in the report, even if they're never imported.
print("\nInitializing session\n", flush=True)
subprocess.run(
[
sys.executable,
"-m",
"coverage",
"run",
"--source",
",".join([os.path.join(src_dir, "websockets"), "tests"]),
"--omit",
",".join(get_ignored_files(src_dir)),
"-m",
"unittest",
]
+ list(UNMAPPED_TEST_FILES),
check=True,
)
# Append coverage of each source module by the corresponding test module.
for src_file, test_file in mapping.items():
print(f"\nTesting {src_file} with {test_file}\n", flush=True)
subprocess.run(
[
sys.executable,
"-m",
"coverage",
"run",
"--append",
"--include",
",".join([os.path.join(src_dir, src_file), test_file]),
"-m",
"unittest",
test_file,
],
check=True,
)
if __name__ == "__main__":
if not check_environment():
sys.exit(1)
src_dir = sys.argv[1] if len(sys.argv) == 2 else "src"
mapping = get_mapping(src_dir)
run_coverage(mapping, src_dir)