-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate_test_modules.py
145 lines (116 loc) · 4.98 KB
/
generate_test_modules.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
from pathlib import Path
from from_root import from_root
from icecream import ic
from typing import List, Tuple
SOURCE_PACKAGES = ["src"]
def generate_source_package_paths() -> List[Path]:
source_package_paths = [Path(folder) for folder in SOURCE_PACKAGES]
return source_package_paths
def generate_source_module_paths(source_package_paths: Path) -> List[Path]:
source_module_paths: List[Path] = list()
[
source_module_paths.extend(source_package_path.glob("*/*.py"))
for source_package_path in source_package_paths
]
return source_module_paths
def generate_test_module_paths(source_module_paths: List[Path]) -> List[Path]:
test_module_paths = []
for path in source_module_paths:
if path.name == "__init__.py":
test_module_paths.append(
Path("tests")
/ path.parent.relative_to(tuple(path.parents)[-1])
/ f"test_{path.parent.name}.py"
)
continue
test_module_paths.append(
Path("tests")
/ path.parent.relative_to(tuple(path.parents)[-1])
/ f"test_{path.name}"
)
return test_module_paths
def create_test_subdirectories(test_module_paths: List[Path]) -> None:
for path in test_module_paths:
from_root(path.parent, mkdirs=True)
def generate_test_modules(source_module_paths, test_module_paths: List[Path]) -> None:
for source_path, test_module_path in zip(source_module_paths, test_module_paths):
(
detected_functions_declarations,
detected_class_declarations,
) = detect_module_objects(source_path)
write_module_contents(
source_path,
test_module_path,
detected_functions_declarations,
detected_class_declarations,
)
def detect_module_objects(source_path: Path) -> Tuple[List[str], List[str]]:
with open(source_path, "r") as fp:
file_contents = fp.readlines()
detected_functions_declarations = detect_function_declarations(file_contents)
detected_class_declarations = detect_class_declarations(file_contents)
ic(detected_functions_declarations)
ic(detected_class_declarations)
return detected_functions_declarations, detected_class_declarations
def write_module_contents(
source_path: Path,
test_module_path: Path,
detected_functions_declarations: List[str],
detected_class_declarations: List[str],
) -> None:
if test_module_path.exists():
print(f"{test_module_path} exists, not overwriting")
return
with open(test_module_path, "w") as fp:
def source_path_template(source_path):
return f"# LINK {source_path}:1\n" f"\n"
def generic_test_function_template(test_module_path):
return (
f"def {test_module_path.stem}():\n"
f" raise NotImplementedError\n"
f"\n"
)
def test_function_template(function_declaration, function_name):
return (
f"def test_{function_name}():\n"
f" raise NotImplementedError\n"
f" {function_declaration}\n"
f"\n"
)
def test_class_template(class_declaration):
return (
f"def test_{class_declaration}():\n"
f" raise NotImplementedError\n"
f" object_to_test = {class_declaration}()\n"
f"\n"
)
fp.writelines(source_path_template(source_path))
if not any((detected_functions_declarations, detected_class_declarations)):
fp.writelines(generic_test_function_template(test_module_path))
for function_declaration in detected_functions_declarations:
function_name = function_declaration[: function_declaration.rindex("(") - 1]
fp.writelines(test_function_template(function_declaration, function_name))
for class_declaration in detected_class_declarations:
fp.writelines(test_class_template(class_declaration))
def detect_class_declarations(file_contents: List[str]) -> List[str]:
filter_term = "class "
filter_term_length = len(filter_term)
return [
line.split(filter_term)[1][: line.rindex("(") - filter_term_length]
if "(" in line
else line.split(filter_term)[1][: line.rindex(":") - filter_term_length]
for line in file_contents
if line.startswith(filter_term)
]
def detect_function_declarations(file_contents: List[str]) -> List[str]:
return [
line.split("def ")[1][: line.rindex(":") - 1]
for line in file_contents
if line.startswith("def ")
]
if __name__ == "__main__":
source_package_paths = generate_source_package_paths()
source_module_paths = generate_source_module_paths(source_package_paths)
test_module_paths = generate_test_module_paths(source_module_paths)
create_test_subdirectories(test_module_paths)
generate_test_modules(source_module_paths, test_module_paths)