Skip to content

Commit

Permalink
Optimize run_tests.py script
Browse files Browse the repository at this point in the history
 * Solve maximum recursion depth issue
 * Add instructions to README.md
 * Add example of usage at top of script
  • Loading branch information
Scandie committed Feb 21, 2018
1 parent 940bd20 commit 41de673
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 50 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
104 changes: 55 additions & 49 deletions run_tests.py
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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)
Expand All @@ -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()

0 comments on commit 41de673

Please sign in to comment.