# HG changeset patch # User Santeri Piippo # Date 1516621873 -7200 # Node ID 09cc89622262d893b53db9fed453209eaa7c69f0 # Parent 45b3aeb25003b322cb427290b0dc852995c7b46f Commit work done on test loading diff -r 45b3aeb25003 -r 09cc89622262 tests/concave.py --- a/tests/concave.py Mon Jan 22 01:01:10 2018 +0200 +++ b/tests/concave.py Mon Jan 22 13:51:13 2018 +0200 @@ -14,23 +14,31 @@ for v1, v2, v3 in pairs(geometry.vertices, count = 3) ] if not sign_consistency(z_scores): - yield error(quadrilateral, 'Concave quadrilateral') - -def bowtie_quadrilateral_test(model): - ... + yield error(quadrilateral, 'concave-error') def skew_test(model): + ''' Test for non-coplanar quadrilaterals. ''' for quadrilateral in model.quadrilaterals: for triangles in split_quadrilateral(quadrilateral.geometry): plane_1 = triangle_plane_normal(triangles[0]) plane_2 = triangle_plane_normal(triangles[1]) - angle = vector_angle(plane_1, plane_2, normalized = True) - if angle > radians(0.1): - yield error(quadrilateral, - 'Skew quadrilateral (plane angle {}°)', - '%.3f' % degrees(angle)) + skew_angle = vector_angle(plane_1, plane_2, normalized = True) + if skew_angle > radians(0.1): + yield error(quadrilateral, 'skew-error', + skew_angle = skew_angle, + ) break manifest = { - 'tests': {skew_test, concave_test}, + 'tests': { + 'skew': skew_test, + 'concave': concave_test, + }, + 'messages': { + 'skew-error': lambda skew_angle: + str.format('Skew quadrilateral (plane angle {}°)', + '%.2f' % degrees(skew_angle), + ), + 'concave-error': 'Concave quadrilateral', + }, } diff -r 45b3aeb25003 -r 09cc89622262 testsuite.py --- a/testsuite.py Mon Jan 22 01:01:10 2018 +0200 +++ b/testsuite.py Mon Jan 22 13:51:13 2018 +0200 @@ -1,13 +1,72 @@ -def warning(object, *message): +from warnings import warn + +def report_element(bad_object, type, error_name, args): return { - 'type': 'warning', - 'object': object, - 'message': str.format(*message), + 'type': type, + 'object': bad_object, + 'name': error_name, + 'args': args, } -def error(object, *message): - return { - 'type': 'error', - 'object': object, - 'message': str.format(*message), - } +def warning(bad_object, error_name, *args): + return report_element(bad_object, 'warning', error_name, args) + +def error(bad_object, error_name, *args): + return report_element(bad_object, 'error', error_name, args) + +def test_discovery(): + ''' + Finds all test modules and yields their names. + ''' + from pkgutil import walk_packages + import tests + yield from sorted( + 'tests.' + result.name + for result in walk_packages(tests.__path__) + ) + +def do_manifest_integrity_checks(test_suite, module): + ''' + Runs integrity checks on a given module's manifest. + ''' + def check_for_extra_keys(): + extra_keys = module.manifest.keys() - test_suite.keys() + if extra_keys: + warn(str.format( + '{}: extra keys in manifest: {}', + module.__name__, + ', '.join(map(str, extra_keys)) + )) + def check_for_manifest_duplicates(): + for key in test_suite.keys(): + duplicates = module.manifest[key].keys() & test_suite[key].keys() + if duplicates: + warn(str.format( + '{}: redefined {} in manifests: {}', + module.__name__, + key, + duplicates, + )) + check_for_extra_keys() + check_for_manifest_duplicates() + +def load_tests(): + ''' + Imports test modules and combines their manifests into a test suite. + ''' + test_suite = {'tests': {}, 'messages': {}} + for module_name in test_discovery(): + from importlib import import_module + module = import_module(module_name) + if hasattr(module, 'manifest'): + do_manifest_integrity_checks(test_suite, module) + # Merge the data from the manifest + for key in module.manifest.keys() & test_suite.keys(): + test_suite[key].update(module.manifest[key]) + else: + warn(str.format('Module {} does not have a manifest', module_name)) + return test_suite + +if __name__ == '__main__': + from pprint import pprint + pprint(load_tests())