Fri, 18 Sep 2020 21:13:58 +0300
added physical color unit 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() |