Fri, 18 Sep 2020 21:05:55 +0300
added unknown subfile test
117 | 1 | #!/usr/bin/env python3 |
2 | from ldcheck import appname, version, version_string | |
122 | 3 | from ldcheck import load_config, find_ldconfig_ldr_paths |
117 | 4 | from ldcheck import script_directory |
5 | from pathlib import Path | |
6 | from parse import read_ldraw | |
7 | from testsuite import load_tests, check_model, problem_text, all_problem_type_names | |
8 | ||
9 | def unit_test_discovery(): | |
10 | ''' Yields unit test paths ''' | |
11 | import os | |
12 | unit_test_dir = Path(script_directory) / 'unittests' | |
13 | for dirpath, dirnames, filenames in os.walk(unit_test_dir): | |
120 | 14 | yield from sorted( |
117 | 15 | Path(dirpath) / filename |
16 | for filename in filenames | |
17 | if filename.endswith('.test') | |
18 | ) | |
19 | ||
20 | def parse_expectation(text): | |
21 | problem_type, line_no_str = str.split(text, ':') | |
22 | return problem_type, int(line_no_str) | |
23 | ||
24 | def load_unit_test(unit_test_path, *, name, ldraw_directories): | |
25 | with open(unit_test_path, 'rb') as device: | |
26 | import re | |
27 | problem_types = set() | |
126
16dae12ac0f0
added bad line ending test
Teemu Piippo <teemu@hecknology.net>
parents:
123
diff
changeset
|
28 | expecting = None |
117 | 29 | while True: |
30 | pos = device.tell() | |
31 | line = bytes.decode(device.readline()) | |
32 | if not line: | |
33 | raise ValueError('unit test ended unexpectedly') | |
34 | match = re.match('^0 Testing: (.+)', line) | |
35 | if match: | |
36 | set.update(problem_types, match.group(1).split()) | |
126
16dae12ac0f0
added bad line ending test
Teemu Piippo <teemu@hecknology.net>
parents:
123
diff
changeset
|
37 | elif str.strip(line) == '0 Expecting: none': |
16dae12ac0f0
added bad line ending test
Teemu Piippo <teemu@hecknology.net>
parents:
123
diff
changeset
|
38 | expecting = set() |
117 | 39 | else: |
40 | match = re.match('^0 Expecting: (.+)', line) | |
41 | if match: | |
126
16dae12ac0f0
added bad line ending test
Teemu Piippo <teemu@hecknology.net>
parents:
123
diff
changeset
|
42 | if not expecting: |
16dae12ac0f0
added bad line ending test
Teemu Piippo <teemu@hecknology.net>
parents:
123
diff
changeset
|
43 | expecting = set() |
117 | 44 | set.update(expecting, map(parse_expectation, match.group(1).split())) |
45 | else: | |
46 | device.seek(pos) | |
47 | break | |
126
16dae12ac0f0
added bad line ending test
Teemu Piippo <teemu@hecknology.net>
parents:
123
diff
changeset
|
48 | if not problem_types or expecting is None: |
117 | 49 | raise ValueError(str.format( |
50 | 'Unit test {name} does not have a proper manifest', | |
51 | name = name, | |
52 | )) | |
53 | return { | |
54 | 'problem_types': problem_types, | |
55 | 'expecting': expecting, | |
56 | 'model': read_ldraw( | |
57 | device, | |
58 | name = name, | |
59 | ldraw_directories = ldraw_directories | |
60 | ), | |
61 | } | |
62 | ||
63 | def parse_problem(problem): | |
64 | return problem.problem_class.name, problem.line_number | |
65 | ||
66 | def run_unit_test(unit_test_path, *, config, test_suite): | |
67 | from os.path import basename | |
68 | unit_test = load_unit_test( | |
69 | unit_test_path, | |
70 | name = basename(unit_test_path), | |
71 | ldraw_directories = config['libraries'], | |
72 | ) | |
73 | bad_problems = set.difference( | |
74 | unit_test['problem_types'], | |
75 | all_problem_type_names(test_suite) | |
76 | ) | |
77 | if bad_problems: | |
78 | raise ValueError(str.format( | |
79 | 'unknown problem type: {names}', | |
80 | names = ' '.join(sorted(bad_problems)) | |
81 | )) | |
82 | problem_types = unit_test['problem_types'] | |
83 | report = check_model(unit_test['model'], test_suite) | |
84 | expected_problems = unit_test['expecting'] | |
85 | problems = set( | |
86 | filter( | |
87 | lambda problem: problem[0] in problem_types, | |
88 | map( | |
89 | parse_problem, | |
90 | report['problems'] | |
91 | ) | |
92 | ) | |
93 | ) | |
94 | return { | |
95 | 'passed': problems == expected_problems, | |
96 | 'unexpected': set.difference(problems, expected_problems), | |
97 | 'missing': set.difference(expected_problems, problems), | |
123
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
98 | 'problem_types': problem_types, |
117 | 99 | } |
100 | ||
101 | def format_problem_tuple(problem_tuple): | |
102 | return problem_tuple[0] + ':' + str(problem_tuple[1]) | |
103 | ||
104 | def run_unit_test_suite(): | |
127
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
105 | from argparse import ArgumentParser |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
106 | parser = ArgumentParser() |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
107 | parser.add_argument('-d', '--debug', action = 'store_true') |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
108 | args = parser.parse_args() |
117 | 109 | config = load_config() |
110 | test_suite = load_tests() | |
111 | num_tested = 0 | |
112 | num_passed = 0 | |
123
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
113 | all_problem_types = all_problem_type_names(test_suite) |
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
114 | problem_types_tested = set() |
117 | 115 | print('Running unit test suite.') |
116 | for unit_test_path in unit_test_discovery(): | |
117 | try: | |
118 | unit_test_report = run_unit_test( | |
119 | unit_test_path, | |
120 | config = config, | |
121 | test_suite = test_suite | |
122 | ) | |
123 | except Exception as error: | |
127
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
124 | if args.debug: |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
125 | raise |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
126 | else: |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
127 | print(str.format( |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
128 | 'Error running {test_name}: {error}', |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
129 | test_name = unit_test_path.name, |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
130 | error = str(error), |
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
126
diff
changeset
|
131 | )) |
117 | 132 | else: |
133 | print(str.format( | |
134 | '{name}: {verdict}', | |
135 | name = unit_test_path.name, | |
136 | verdict = ('FAILED', 'PASSED')[unit_test_report['passed']], | |
137 | )) | |
138 | num_tested += 1 | |
139 | num_passed += int(unit_test_report['passed']) | |
123
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
140 | set.update(problem_types_tested, unit_test_report['problem_types']) |
117 | 141 | if not unit_test_report['passed']: |
142 | def format_problem_list(key): | |
143 | return str.join( | |
144 | ' ', | |
145 | map(format_problem_tuple, unit_test_report[key]) | |
146 | ) | |
147 | print('\tunexpected:', format_problem_list('unexpected')) | |
148 | print('\tmissing:', format_problem_list('missing')) | |
149 | print(str.format( | |
150 | '{num_tested} tests run, {num_passed} tests passed.', | |
151 | num_tested = num_tested, | |
152 | num_passed = num_passed, | |
153 | )) | |
123
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
154 | untested_problem_types = set.difference(all_problem_types, problem_types_tested) |
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
155 | if untested_problem_types: |
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
156 | print('The following problem types were not tested:') |
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
157 | for problem_type in sorted(untested_problem_types): |
0557709c25ec
added a todo list for unit tests
Teemu Piippo <teemu@hecknology.net>
parents:
122
diff
changeset
|
158 | print('\t' + problem_type) |
117 | 159 | if __name__ == '__main__': |
160 | run_unit_test_suite() |