|
| 1 | +""" Very hacky script that runs tests on bike share systems that have |
| 2 | +changed on a specific branch. Checks for changes on data files and |
| 3 | +classes containing bike share systems. |
| 4 | +
|
| 5 | +This is meant for red explicit fails on changes in CI |
| 6 | +""" |
| 7 | + |
| 8 | +import re |
| 9 | +import os |
| 10 | +import git |
| 11 | +import inspect |
| 12 | + |
| 13 | +from pytest import mark |
| 14 | +from warnings import warn |
| 15 | + |
| 16 | +from pybikes import BikeShareSystem |
| 17 | +from pybikes.data import get_instances |
| 18 | +from pybikes.compat import resources |
| 19 | + |
| 20 | +from tests.test_instances import get_test_cls |
| 21 | + |
| 22 | + |
| 23 | +def is_system(mod, obj): |
| 24 | + if not inspect.isclass(obj): |
| 25 | + return False |
| 26 | + |
| 27 | + # Only declared in module |
| 28 | + if obj.__module__ != mod.__name__: |
| 29 | + return False |
| 30 | + |
| 31 | + if not issubclass(obj, BikeShareSystem): |
| 32 | + return False |
| 33 | + |
| 34 | + if obj == BikeShareSystem: |
| 35 | + return False |
| 36 | + |
| 37 | + return True |
| 38 | + |
| 39 | + |
| 40 | +def generate_tests_from_changes(branch): |
| 41 | + |
| 42 | + # this will fail in python < 3.8 |
| 43 | + from importlib.util import spec_from_file_location, module_from_spec |
| 44 | + |
| 45 | + # this might fail if branch not in git dir |
| 46 | + g = git.cmd.Git(os.getcwd()) |
| 47 | + changed_files = g.diff('--name-only', branch).splitlines() |
| 48 | + clss = set() |
| 49 | + |
| 50 | + for file in changed_files: |
| 51 | + if re.match(r'pybikes/data/.*\.json', file): |
| 52 | + # Extract classes from json file |
| 53 | + match = re.search(r'pybikes/data/(.*)\.json', file) |
| 54 | + schema = match.group(1) |
| 55 | + [clss.add(cls) for cls, _ in get_instances(schema)] |
| 56 | + elif re.match(r'pybikes/.*\.py', file): |
| 57 | + # Extract bike share classes from file |
| 58 | + spec = spec_from_file_location('some.mod', file) |
| 59 | + mod = module_from_spec(spec) |
| 60 | + spec.loader.exec_module(mod) |
| 61 | + systems = filter(lambda m: is_system(mod, m[1]), inspect.getmembers(mod)) |
| 62 | + [clss.add(cls) for cls, _ in systems] |
| 63 | + |
| 64 | + for cls in sorted(clss): |
| 65 | + test_cls = get_test_cls(cls) |
| 66 | + # decorate with pytest mark 'changes' |
| 67 | + test_cls = mark.changes(test_cls) |
| 68 | + globals()[test_cls.__name__] = test_cls |
| 69 | + |
| 70 | + |
| 71 | +# non-optimal not-required |
| 72 | +try: |
| 73 | + generate_tests_from_changes('origin/master') |
| 74 | +except Exception as e: |
| 75 | + warn("Failed generating tests from branch changes: " + str(e)) |
| 76 | + |
| 77 | +# Force pytest to succeed when no tests are marked with 'changes' |
| 78 | +@mark.changes |
| 79 | +def test_dummy(): |
| 80 | + assert True |
0 commit comments