From 940bd2003b4a2d0787f9e75d56dd5c4c3763f28d Mon Sep 17 00:00:00 2001 From: Scandie Date: Tue, 20 Feb 2018 15:35:53 +0200 Subject: [PATCH 1/2] Add script for running all tests from inner buildout packages --- run_tests.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 run_tests.py diff --git a/run_tests.py b/run_tests.py new file mode 100644 index 00000000..630ee072 --- /dev/null +++ b/run_tests.py @@ -0,0 +1,92 @@ +import sys +import os +import nose +import argparse +from pkg_resources import iter_entry_points +import logging + +DEFAULT_PACKAGES = ['openprocurement'] # default packages that should be tested +DEFAULT_RECURSION_LIMIT = 1000 +NOSE_ENV = { + "NOSE_WITH_XUNIT": 1, + "NOSE_WITH_COVERAGE": 1, + "NOSE_COVER_PACKAGE": [], + "NOSE_COVER_ERASE": 1, + "NOSE_COVER_HTML": 1, + "NOSE_PROCESSES": 0, + "NOSE_WITH_DOCTEST": 1, + "NOSE_NOCAPTURE": 1, + "NOSE_VERBOSE": 1, +} +os.environ['PYTEST_ADDOPTS'] = '--ignore=src/ --junitxml=pytest.xml' + + +def set_recursion_limit(tests_amount): + """ + Increase default python recursion depth limit + if tests amount is greater than that value + """ + if (DEFAULT_RECURSION_LIMIT - tests_amount) < DEFAULT_RECURSION_LIMIT / 2: + sys.setrecursionlimit(tests_amount + DEFAULT_RECURSION_LIMIT) + + +def get_tests(packages, test_type): + tested_packages = list() + all_tests = list() + for pack in packages: + group = pack.split('.')[0] if pack.split('.')[0:1] else None + if group is None: + continue + for entry_point in iter_entry_points(group=group + '.' + test_type): + package_name = group + '.{}' + package_name = package_name.format(entry_point.name) + tested_packages.append(package_name) + suite = entry_point.load() + if package_name.startswith(pack): + if test_type == 'tests': + for tests in suite(): + all_tests.append(tests) + elif test_type == 'pytests': + all_tests.append(suite) + return all_tests, tested_packages + + +def unpack_suites(suites): + tests = list() + for suite in suites: + if hasattr(suite, '_tests'): + tests += unpack_suites(suite._tests) + else: + tests.append(suite) + return tests + + +if __name__ == '__main__': + logger = logging.getLogger('console_output') + logger.setLevel(logging.INFO) + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + logger.addHandler(console_handler) + parser = argparse.ArgumentParser(description='Test some packages.') + parser.add_argument('packages', metavar='P', type=str, nargs='*', + help='name of packages to test', default=DEFAULT_PACKAGES) + parser.add_argument('--list-packages', dest='list_packages', action='store_const', + const=True, default=False, + help='List packages that can be tested') + args = parser.parse_args() + unique_packages = set(args.packages) + nose_tests, cover_packages = get_tests(unique_packages, 'tests') + pytests, pytest_packages = get_tests(unique_packages, 'pytests') + if args.list_packages: + logger.info('NOSETESTS:') + for p in cover_packages: + logger.info("> {}".format(p)) + logger.info('PYTESTS:') + for p in pytest_packages: + logger.info("> {}".format(p)) + exit() + NOSE_ENV['NOSE_COVER_PACKAGE'] = cover_packages + unpacked_tests = unpack_suites(nose_tests) + set_recursion_limit(len(unpacked_tests)) + sys.exit([suite() for suite in pytests], + nose.run_exit(suite=unpacked_tests, env=NOSE_ENV)) From 41de673c04484859ff49ef51b0efa364086a1f7b Mon Sep 17 00:00:00 2001 From: Scandie Date: Wed, 21 Feb 2018 17:09:00 +0200 Subject: [PATCH 2/2] Optimize run_tests.py script * Solve maximum recursion depth issue * Add instructions to README.md * Add example of usage at top of script --- README.md | 13 ++++++- run_tests.py | 104 +++++++++++++++++++++++++++------------------------ 2 files changed, 67 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index a17b75c7..96bb1a93 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,18 @@ To start environment services: bin/circusd --daemon -To to run openprocurement.api instance: +To run openprocurement.api instance: bin/pserve etc/openprocurement.api.ini +To run tests: + + bin/python run_tests.py + +To print packages that will be tested to console: + + bin/python run_tests.py --list-packages + +To specify groups of packages that should be tested: + + bin/python run_tests.py openprocurement diff --git a/run_tests.py b/run_tests.py index 630ee072..5e528d96 100644 --- a/run_tests.py +++ b/run_tests.py @@ -1,12 +1,18 @@ -import sys -import os -import nose +""" +Example of usage: + +bin/python run_tests.py run tests for packages groups specified in DEFAULT_PACKAGES +bin/python run_tests.py openprocurement specify packages groups to run tests for +bin/python run_tests.py --list-packages show packages that will be tested without actually running them +""" import argparse -from pkg_resources import iter_entry_points import logging +import os +from pkg_resources import iter_entry_points + +import nose -DEFAULT_PACKAGES = ['openprocurement'] # default packages that should be tested -DEFAULT_RECURSION_LIMIT = 1000 +DEFAULT_PACKAGES = ['openprocurement'] # default groups of packages that should be tested NOSE_ENV = { "NOSE_WITH_XUNIT": 1, "NOSE_WITH_COVERAGE": 1, @@ -21,52 +27,54 @@ os.environ['PYTEST_ADDOPTS'] = '--ignore=src/ --junitxml=pytest.xml' -def set_recursion_limit(tests_amount): +def get_tests(packages, test_type): """ - Increase default python recursion depth limit - if tests amount is greater than that value + Collect tests from entry points of specified packages. + :param packages: list of strings, which are representing groups of packages that should be tested. + :param test_type: 'tests' or 'pytests' for unittest TestCases and pytest test respectively. + :return: test suites collected from entry points; + list of strings, which are representing packages that will be tested. """ - if (DEFAULT_RECURSION_LIMIT - tests_amount) < DEFAULT_RECURSION_LIMIT / 2: - sys.setrecursionlimit(tests_amount + DEFAULT_RECURSION_LIMIT) - - -def get_tests(packages, test_type): tested_packages = list() all_tests = list() for pack in packages: - group = pack.split('.')[0] if pack.split('.')[0:1] else None - if group is None: - continue - for entry_point in iter_entry_points(group=group + '.' + test_type): - package_name = group + '.{}' - package_name = package_name.format(entry_point.name) + for entry_point in iter_entry_points(group='{}.{}'.format(pack, test_type)): + package_name = '{}.{}'.format(pack, entry_point.name) tested_packages.append(package_name) suite = entry_point.load() - if package_name.startswith(pack): - if test_type == 'tests': - for tests in suite(): - all_tests.append(tests) - elif test_type == 'pytests': - all_tests.append(suite) + if test_type == 'tests': + for tests in suite(): + all_tests.extend(tests) + elif test_type == 'pytests': + all_tests.append(suite) return all_tests, tested_packages -def unpack_suites(suites): - tests = list() - for suite in suites: - if hasattr(suite, '_tests'): - tests += unpack_suites(suite._tests) - else: - tests.append(suite) - return tests - - -if __name__ == '__main__': +def setup_logger(): logger = logging.getLogger('console_output') logger.setLevel(logging.INFO) console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) logger.addHandler(console_handler) + return logger + + +def list_packages(cover_packages, pytest_packages, logger): + """ + Print to console names of packages that will be tested, without running tests. + """ + if cover_packages: + logger.info('NOSETESTS:') + for p in cover_packages: + logger.info("> {}".format(p)) + if pytest_packages: + logger.info('PYTESTS:') + for p in pytest_packages: + logger.info("> {}".format(p)) + + +def run(): + logger = setup_logger() parser = argparse.ArgumentParser(description='Test some packages.') parser.add_argument('packages', metavar='P', type=str, nargs='*', help='name of packages to test', default=DEFAULT_PACKAGES) @@ -78,15 +86,13 @@ def unpack_suites(suites): nose_tests, cover_packages = get_tests(unique_packages, 'tests') pytests, pytest_packages = get_tests(unique_packages, 'pytests') if args.list_packages: - logger.info('NOSETESTS:') - for p in cover_packages: - logger.info("> {}".format(p)) - logger.info('PYTESTS:') - for p in pytest_packages: - logger.info("> {}".format(p)) - exit() - NOSE_ENV['NOSE_COVER_PACKAGE'] = cover_packages - unpacked_tests = unpack_suites(nose_tests) - set_recursion_limit(len(unpacked_tests)) - sys.exit([suite() for suite in pytests], - nose.run_exit(suite=unpacked_tests, env=NOSE_ENV)) + list_packages(cover_packages, pytest_packages, logger) + else: + NOSE_ENV['NOSE_COVER_PACKAGE'] = cover_packages + for suite in pytests: + suite() + nose.run(suite=nose_tests, env=NOSE_ENV) + + +if __name__ == '__main__': + run()