Skip to content

Commit c933a79

Browse files
committed
Update run_tests.py
1 parent 6dd5f5e commit c933a79

File tree

1 file changed

+90
-76
lines changed

1 file changed

+90
-76
lines changed

utbot-python/samples/run_tests.py

Lines changed: 90 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import json
1212
import os
1313
import shutil
14+
from subprocess import Popen, PIPE
1415
import sys
16+
import threading
1517
import typing
1618
import tqdm
1719
from tqdm.contrib import DummyTqdmFile
@@ -20,44 +22,27 @@
2022

2123
def parse_arguments():
2224
parser = argparse.ArgumentParser(
23-
prog='UtBot Python test',
24-
description='Generate tests for example files'
25+
prog="UtBot Python test", description="Generate tests for example files"
2526
)
2627
subparsers = parser.add_subparsers(dest="command")
27-
parser_generate = subparsers.add_parser('generate', help='Generate tests')
28-
parser_generate.add_argument('java')
29-
parser_generate.add_argument('jar')
30-
parser_generate.add_argument('path_to_test_dir')
31-
parser_generate.add_argument('-c', '--config_file', required=True)
32-
parser_generate.add_argument('-p', '--python_path', required=True)
33-
parser_generate.add_argument('-o', '--output_dir', required=True)
34-
parser_generate.add_argument('-i', '--coverage_output_dir', required=True)
35-
parser_run = subparsers.add_parser('run', help='Run tests')
36-
parser_run.add_argument('-p', '--python_path', required=True)
37-
parser_run.add_argument('-t', '--test_directory', required=True)
38-
parser_run.add_argument('-c', '--code_directory', required=True)
39-
parser_coverage = subparsers.add_parser('check_coverage', help='Check coverage')
40-
parser_coverage.add_argument('-i', '--coverage_output_dir', required=True)
41-
parser_coverage.add_argument('-c', '--config_file', required=True)
28+
parser_generate = subparsers.add_parser("generate", help="Generate tests")
29+
parser_generate.add_argument("java")
30+
parser_generate.add_argument("jar")
31+
parser_generate.add_argument("path_to_test_dir")
32+
parser_generate.add_argument("-c", "--config_file", required=True)
33+
parser_generate.add_argument("-p", "--python_path", required=True)
34+
parser_generate.add_argument("-o", "--output_dir", required=True)
35+
parser_generate.add_argument("-i", "--coverage_output_dir", required=True)
36+
parser_run = subparsers.add_parser("run", help="Run tests")
37+
parser_run.add_argument("-p", "--python_path", required=True)
38+
parser_run.add_argument("-t", "--test_directory", required=True)
39+
parser_run.add_argument("-c", "--code_directory", required=True)
40+
parser_coverage = subparsers.add_parser("check_coverage", help="Check coverage")
41+
parser_coverage.add_argument("-i", "--coverage_output_dir", required=True)
42+
parser_coverage.add_argument("-c", "--config_file", required=True)
4243
return parser.parse_args()
4344

4445

45-
def inner_zip(collection: dict[str, typing.Iterable], keys: list[str]) -> typing.Iterator[list[typing.Any]]:
46-
key, inner_keys = keys[0], keys[1:]
47-
if len(inner_keys) == 0:
48-
yield [collection[key]]
49-
return
50-
for inner_collection in collection[key]:
51-
for group in inner_zip(inner_collection, inner_keys):
52-
yield [collection[key]] + group
53-
54-
55-
def test_inner_zip():
56-
data = {"1": [{"2": [1, 2, 3]}, {"2": [4, 5, 6]}]}
57-
actual = inner_zip(data, ["1", "2"])
58-
assert list(actual) == [[data["1"], data["1"][0]["2"]], [data["1"], data["1"][1]["2"]]]
59-
60-
6146
def parse_config(config_path: str):
6247
with open(config_path, "r") as fin:
6348
return json.loads(fin.read())
@@ -78,31 +63,37 @@ def std_out_err_redirect_tqdm():
7863

7964

8065
def generate_tests(
81-
java: str,
82-
jar_path: str,
83-
sys_paths: list[str],
84-
python_path: str,
85-
file_under_test: str,
86-
timeout: int,
87-
output: str,
88-
coverage_output: str,
89-
class_names: typing.Optional[list[str]] = None,
90-
method_names: typing.Optional[list[str]] = None
91-
):
66+
java: str,
67+
jar_path: str,
68+
sys_paths: list[str],
69+
python_path: str,
70+
file_under_test: str,
71+
timeout: int,
72+
output: str,
73+
coverage_output: str,
74+
class_names: typing.Optional[list[str]] = None,
75+
method_names: typing.Optional[list[str]] = None,
76+
):
9277
command = f"{java} -jar {jar_path} generate_python {file_under_test}.py -p {python_path} -o {output} -s {' '.join(sys_paths)} --timeout {timeout * 1000} --install-requirements --runtime-exception-behaviour PASS --coverage={coverage_output}"
9378
if class_names is not None:
9479
command += f" -c {','.join(class_names)}"
9580
if method_names is not None:
9681
command += f" -m {','.join(method_names)}"
97-
tqdm.tqdm.write(command)
98-
code = os.system(command)
99-
return code
82+
tqdm.tqdm.write("\n" + command)
83+
84+
def stdout_printer(p):
85+
for line in p.stdout:
86+
tqdm.tqdm.write(line.rstrip().decode())
87+
88+
p = Popen(command.split(), stdout=PIPE)
89+
t = threading.Thread(target=stdout_printer, args=(p,))
90+
t.run()
10091

10192

10293
def run_tests(
103-
python_path: str,
104-
tests_dir: str,
105-
samples_dir: str,
94+
python_path: str,
95+
tests_dir: str,
96+
samples_dir: str,
10697
):
10798
command = f'{python_path} -m coverage run --source={samples_dir} -m unittest discover -p "utbot_*" {tests_dir}'
10899
tqdm.tqdm.write(command)
@@ -111,28 +102,38 @@ def run_tests(
111102

112103

113104
def check_coverage(
114-
config_file: str,
115-
coverage_output_dir: str,
105+
config_file: str,
106+
coverage_output_dir: str,
116107
):
117108
config = parse_config(config_file)
118109
report: typing.Dict[str, bool] = {}
119110
coverage: typing.Dict[str, typing.Tuple[float, float]] = {}
120-
for part in config['parts']:
121-
for file in part['files']:
122-
for group in file['groups']:
123-
expected_coverage = group.get('coverage', 0)
111+
for part in config["parts"]:
112+
for file in part["files"]:
113+
for group in file["groups"]:
114+
expected_coverage = group.get("coverage", 0)
124115

125116
file_suffix = f"{part['path'].replace('/', '_')}_{file['name']}"
126-
coverage_output_file = pathlib.Path(coverage_output_dir, f"coverage_{file_suffix}.json")
117+
coverage_output_file = pathlib.Path(
118+
coverage_output_dir, f"coverage_{file_suffix}.json"
119+
)
127120
if coverage_output_file.exists():
128121
with open(coverage_output_file, "rt") as fin:
129122
actual_coverage_json = json.loads(fin.readline())
130-
actual_covered = sum(lines['end'] - lines['start'] + 1 for lines in actual_coverage_json['covered'])
131-
actual_not_covered = sum(lines['end'] - lines['start'] + 1 for lines in actual_coverage_json['notCovered'])
123+
actual_covered = sum(
124+
lines["end"] - lines["start"] + 1
125+
for lines in actual_coverage_json["covered"]
126+
)
127+
actual_not_covered = sum(
128+
lines["end"] - lines["start"] + 1
129+
for lines in actual_coverage_json["notCovered"]
130+
)
132131
if actual_covered + actual_not_covered == 0:
133132
actual_coverage = 0
134133
else:
135-
actual_coverage = round(actual_covered / (actual_not_covered + actual_covered) * 100)
134+
actual_coverage = round(
135+
actual_covered / (actual_not_covered + actual_covered) * 100
136+
)
136137
else:
137138
actual_coverage = 0
138139

@@ -154,32 +155,45 @@ def main_test_generation(args):
154155
if pathlib.Path(args.coverage_output_dir).exists():
155156
shutil.rmtree(args.coverage_output_dir)
156157
with std_out_err_redirect_tqdm() as orig_stdout:
157-
# for (part, file, group) in tqdm.tqdm(inner_zip(config, ["parts", "files", "groups"]), file=orig_stdout, dynamic_ncols=True):
158-
for part in tqdm.tqdm(config["parts"], file=orig_stdout, dynamic_ncols=True):
159-
for file in tqdm.tqdm(part["files"], file=orig_stdout, dynamic_ncols=True):
160-
for group in tqdm.tqdm(file["groups"], file=orig_stdout, dynamic_ncols=True):
161-
full_name = pathlib.PurePath(args.path_to_test_dir, part['path'], file['name'])
162-
output_file = pathlib.PurePath(args.output_dir, f"utbot_tests_{part['path'].replace('/', '_')}_{file['name']}.py")
163-
coverage_output_file = pathlib.PurePath(args.coverage_output_dir, f"coverage_{part['path'].replace('/', '_')}_{file['name']}.json")
158+
for part in tqdm.tqdm(
159+
config["parts"], file=orig_stdout, dynamic_ncols=True, desc="Progress"
160+
):
161+
for file in tqdm.tqdm(
162+
part["files"], file=orig_stdout, dynamic_ncols=True, desc=part["path"]
163+
):
164+
for group in file["groups"]:
165+
full_name = pathlib.PurePath(
166+
args.path_to_test_dir, part["path"], file["name"]
167+
)
168+
output_file = pathlib.PurePath(
169+
args.output_dir,
170+
f"utbot_tests_{part['path'].replace('/', '_')}_{file['name']}.py",
171+
)
172+
coverage_output_file = pathlib.PurePath(
173+
args.coverage_output_dir,
174+
f"coverage_{part['path'].replace('/', '_')}_{file['name']}.json",
175+
)
164176
generate_tests(
165177
args.java,
166178
args.jar,
167179
[args.path_to_test_dir],
168180
args.python_path,
169181
str(full_name),
170-
group['timeout'],
182+
group["timeout"],
171183
str(output_file),
172184
str(coverage_output_file),
173-
group['classes'],
174-
group['methods']
185+
group["classes"],
186+
group["methods"],
175187
)
176-
177188

178-
if __name__ == '__main__':
189+
190+
if __name__ == "__main__":
179191
arguments = parse_arguments()
180-
if arguments.command == 'generate':
192+
if arguments.command == "generate":
181193
main_test_generation(arguments)
182-
elif arguments.command == 'run':
183-
run_tests(arguments.python_path, arguments.test_directory, arguments.code_directory)
184-
elif arguments.command == 'check_coverage':
194+
elif arguments.command == "run":
195+
run_tests(
196+
arguments.python_path, arguments.test_directory, arguments.code_directory
197+
)
198+
elif arguments.command == "check_coverage":
185199
check_coverage(arguments.config_file, arguments.coverage_output_dir)

0 commit comments

Comments
 (0)