def django_tests(verbosity, interactive, failfast, keepdb, reverse, test_labels, debug_sql, parallel, tags, exclude_tags, test_name_patterns, start_at, start_after, pdb, buffer, timing): if verbosity >= 1: msg = "Testing against Django installed in '%s'" % os.path.dirname( django.__file__) max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += " with up to %d processes" % max_parallel print(msg) state = setup(verbosity, test_labels, start_at, start_after) # Run the test suite, including the extra validation tests. if not hasattr(settings, 'TEST_RUNNER'): settings.TEST_RUNNER = 'django.test.runner.DiscoverRunner' TestRunner = get_runner(settings) test_runner = TestRunner( verbosity=verbosity, interactive=interactive, failfast=failfast, keepdb=keepdb, reverse=reverse, debug_sql=debug_sql, parallel=actual_test_processes(parallel), tags=tags, exclude_tags=exclude_tags, test_name_patterns=test_name_patterns, pdb=pdb, buffer=buffer, timing=timing, ) failures = test_runner.run_tests(test_labels or get_installed()) teardown(state) return failures
def __init__(self, parallel=1, reset_db=False, **kwargs): if reset_db: kwargs.update({"keepdb": False, "interactive": False}) else: kwargs.update({"keepdb": True}) kwargs.update( {"parallel": default_test_processes() if parallel != 0 else 0}) super().__init__(**kwargs)
def actual_test_processes(parallel): if parallel == 0: # This doesn't work before django.setup() on some databases. if all(conn.features.can_clone_databases for conn in connections.all()): return default_test_processes() else: return 1 else: return parallel
def actual_test_processes(parallel): if parallel == 0: # On Python 3.4+: if multiprocessing.get_start_method() != 'fork': if not hasattr(os, 'fork'): return 1 # This doesn't work before django.setup() on some databases. elif all(conn.features.can_clone_databases for conn in connections.all()): return default_test_processes() else: return 1 else: return parallel
def run_tests(self): import django from django.conf import settings from django.test.runner import default_test_processes from django.test.utils import get_runner django.setup() test_runner_class = get_runner(settings) try: import xmlrunner class XMLTestRunner(test_runner_class): def run_suite(self, suite, **kwargs): verbosity = getattr(settings, 'TEST_OUTPUT_VERBOSE', 1) if isinstance(verbosity, bool): verbosity = (1, 2)[verbosity] descriptions = getattr(settings, 'TEST_OUTPUT_DESCRIPTIONS', False) output = getattr(settings, 'TEST_OUTPUT_DIR', '.') return xmlrunner.XMLTestRunner(verbosity=verbosity, descriptions=descriptions, output=output).run(suite) test_runner_class = XMLTestRunner except ImportError: print( "Not generating XML reports, run 'pip install unittest-xml-reporting' to enable XML report generation" ) if self.parallel: parallel = default_test_processes() else: parallel = 0 test_runner = test_runner_class(verbosity=2, interactive=True, parallel=parallel) failures = test_runner.run_tests([]) sys.exit(bool(failures))
def setup(verbosity, test_labels, parallel, start_at, start_after): # Reduce the given test labels to just the app module path. test_labels_set = set() for label in test_labels: bits = label.split('.')[:1] test_labels_set.add('.'.join(bits)) if verbosity >= 1: msg = "Testing against Django installed in '%s'" % os.path.dirname( django.__file__) max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += " with up to %d processes" % max_parallel print(msg) # Force declaring available_apps in TransactionTestCase for faster tests. def no_available_apps(self): raise Exception("Please define available_apps in TransactionTestCase " "and its subclasses.") TransactionTestCase.available_apps = property(no_available_apps) TestCase.available_apps = None state = { 'INSTALLED_APPS': settings.INSTALLED_APPS, 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), 'TEMPLATES': settings.TEMPLATES, 'LANGUAGE_CODE': settings.LANGUAGE_CODE, 'STATIC_URL': settings.STATIC_URL, 'STATIC_ROOT': settings.STATIC_ROOT, 'MIDDLEWARE': settings.MIDDLEWARE, } # Redirect some settings for the duration of these tests. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = 'urls' settings.STATIC_URL = '/static/' settings.STATIC_ROOT = os.path.join(TMPDIR, 'static') settings.TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [TEMPLATE_DIR], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }] settings.LANGUAGE_CODE = 'en' settings.SITE_ID = 1 settings.MIDDLEWARE = ALWAYS_MIDDLEWARE settings.MIGRATION_MODULES = { # This lets us skip creating migrations for the test models as many of # them depend on one of the following contrib applications. 'auth': None, 'contenttypes': None, 'sessions': None, } log_config = copy.deepcopy(DEFAULT_LOGGING) # Filter out non-error logging so we don't have to capture it in lots of # tests. log_config['loggers']['django']['level'] = 'ERROR' settings.LOGGING = log_config settings.SILENCED_SYSTEM_CHECKS = [ 'fields.W342', # ForeignKey(unique=True) -> OneToOneField ] # Load all the ALWAYS_INSTALLED_APPS. django.setup() # It would be nice to put this validation earlier but it must come after # django.setup() so that connection.features.gis_enabled can be accessed # without raising AppRegistryNotReady when running gis_tests in isolation # on some backends (e.g. PostGIS). if 'gis_tests' in test_labels_set and not connection.features.gis_enabled: print('Aborting: A GIS database backend is required to run gis_tests.') sys.exit(1) def _module_match_label(module_label, label): # Exact or ancestor match. return module_label == label or module_label.startswith(label + '.') # Load all the test model apps. test_modules = get_test_modules() found_start = not (start_at or start_after) installed_app_names = set(get_installed()) for modpath, module_name in test_modules: if modpath: module_label = modpath + '.' + module_name else: module_label = module_name if not found_start: if start_at and _module_match_label(module_label, start_at): found_start = True elif start_after and _module_match_label(module_label, start_after): found_start = True continue else: continue # if the module (or an ancestor) was named on the command line, or # no modules were named (i.e., run all), import # this module and add it to INSTALLED_APPS. module_found_in_labels = not test_labels or any( _module_match_label(module_label, label) for label in test_labels_set) if module_name in CONTRIB_TESTS_TO_APPS and module_found_in_labels: settings.INSTALLED_APPS.append(CONTRIB_TESTS_TO_APPS[module_name]) if module_found_in_labels and module_label not in installed_app_names: if verbosity >= 2: print("Importing application %s" % module_name) settings.INSTALLED_APPS.append(module_label) # Add contrib.gis to INSTALLED_APPS if needed (rather than requiring # @override_settings(INSTALLED_APPS=...) on all test cases. gis = 'django.contrib.gis' if connection.features.gis_enabled and gis not in settings.INSTALLED_APPS: if verbosity >= 2: print("Importing application %s" % gis) settings.INSTALLED_APPS.append(gis) apps.set_installed_apps(settings.INSTALLED_APPS) return state
default=socket.gethostname(), help= 'The external host that can be reached by the selenium hub instance when running Selenium ' 'tests via Selenium Hub.', ) parser.add_argument( '--debug-sql', action='store_true', help='Turn on the SQL query logger within tests.', ) parser.add_argument( '--parallel', nargs='?', default=0, type=int, const=default_test_processes(), metavar='N', help='Run tests using up to N parallel processes.', ) parser.add_argument( '--tag', dest='tags', action='append', help= 'Run only tests with the specified tags. Can be used multiple times.', ) parser.add_argument( '--exclude-tag', dest='exclude_tags', action='append', help=
def setup(verbosity, test_labels, parallel): if verbosity >= 1: msg = "Testing against Django installed in '%s'" % os.path.dirname( django.__file__) max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += " with up to %d processes" % max_parallel print(msg) # Force declaring available_apps in TransactionTestCase for faster tests. def no_available_apps(self): raise Exception("Please define available_apps in TransactionTestCase " "and its subclasses.") TransactionTestCase.available_apps = property(no_available_apps) TestCase.available_apps = None state = { 'INSTALLED_APPS': settings.INSTALLED_APPS, 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), 'TEMPLATES': settings.TEMPLATES, 'LANGUAGE_CODE': settings.LANGUAGE_CODE, 'STATIC_URL': settings.STATIC_URL, 'STATIC_ROOT': settings.STATIC_ROOT, 'MIDDLEWARE_CLASSES': settings.MIDDLEWARE_CLASSES, } # Redirect some settings for the duration of these tests. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = 'urls' settings.STATIC_URL = '/static/' settings.STATIC_ROOT = os.path.join(TMPDIR, 'static') settings.TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [TEMPLATE_DIR], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }] settings.LANGUAGE_CODE = 'en' settings.SITE_ID = 1 settings.MIDDLEWARE_CLASSES = ALWAYS_MIDDLEWARE_CLASSES settings.MIGRATION_MODULES = { # This lets us skip creating migrations for the test models as many of # them depend on one of the following contrib applications. 'auth': None, 'contenttypes': None, 'sessions': None, } log_config = copy.deepcopy(DEFAULT_LOGGING) # Filter out non-error logging so we don't have to capture it in lots of # tests. log_config['loggers']['django']['level'] = 'ERROR' settings.LOGGING = log_config warnings.filterwarnings('ignore', 'The GeoManager class is deprecated.', RemovedInDjango20Warning) # Load all the ALWAYS_INSTALLED_APPS. django.setup() # Load all the test model apps. test_modules = get_test_modules() # Reduce given test labels to just the app module path test_labels_set = set() for label in test_labels: bits = label.split('.')[:1] test_labels_set.add('.'.join(bits)) installed_app_names = set(get_installed()) for modpath, module_name in test_modules: if modpath: module_label = '.'.join([modpath, module_name]) else: module_label = module_name # if the module (or an ancestor) was named on the command line, or # no modules were named (i.e., run all), import # this module and add it to INSTALLED_APPS. if not test_labels: module_found_in_labels = True else: module_found_in_labels = any( # exact match or ancestor match module_label == label or module_label.startswith(label + '.') for label in test_labels_set) if module_name in CONTRIB_TESTS_TO_APPS and module_found_in_labels: settings.INSTALLED_APPS.append(CONTRIB_TESTS_TO_APPS[module_name]) if module_found_in_labels and module_label not in installed_app_names: if verbosity >= 2: print("Importing application %s" % module_name) settings.INSTALLED_APPS.append(module_label) # Add contrib.gis to INSTALLED_APPS if needed (rather than requiring # @override_settings(INSTALLED_APPS=...) on all test cases. gis = 'django.contrib.gis' if connection.features.gis_enabled and gis not in settings.INSTALLED_APPS: if verbosity >= 2: print("Importing application %s" % gis) settings.INSTALLED_APPS.append(gis) apps.set_installed_apps(settings.INSTALLED_APPS) return state
settings.HEADLESS = False test_runner = get_runner(settings) failures = test_runner(parallel=args.parallel).run_tests(args.tests) sys.exit(bool(failures)) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Run tests') parser.add_argument(dest='tests', metavar='testcase', nargs='*', default=['tests'], help='an optional list of test cases to run') parser.add_argument( '--parallel', type=int, nargs='?', const=default_test_processes(), # arg is given without value default=1, # arg is not given help= 'do run multiple tests in parallel (how many if specified, else equal to number of processors)' ) parser.add_argument( '--headful', action='store_true', help='do not run headless (checkout tests running onscreen)') args = parser.parse_args() runtests()
def setup(verbosity, test_labels, parallel): # Reduce the given test labels to just the app module path. test_labels_set = set() for label in test_labels: bits = label.split('.')[:1] test_labels_set.add('.'.join(bits)) if verbosity >= 1: msg = "Testing against Django installed in '%s'" % os.path.dirname(django.__file__) max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += " with up to %d processes" % max_parallel print(msg) # Force declaring available_apps in TransactionTestCase for faster tests. def no_available_apps(self): raise Exception("Please define available_apps in TransactionTestCase " "and its subclasses.") TransactionTestCase.available_apps = property(no_available_apps) TestCase.available_apps = None state = { 'INSTALLED_APPS': settings.INSTALLED_APPS, 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), 'TEMPLATES': settings.TEMPLATES, 'LANGUAGE_CODE': settings.LANGUAGE_CODE, 'STATIC_URL': settings.STATIC_URL, 'STATIC_ROOT': settings.STATIC_ROOT, 'MIDDLEWARE': settings.MIDDLEWARE, } # Redirect some settings for the duration of these tests. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = 'urls' settings.STATIC_URL = '/static/' settings.STATIC_ROOT = os.path.join(TMPDIR, 'static') settings.TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [TEMPLATE_DIR], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }] settings.LANGUAGE_CODE = 'en' settings.SITE_ID = 1 settings.MIDDLEWARE = ALWAYS_MIDDLEWARE settings.MIGRATION_MODULES = { # This lets us skip creating migrations for the test models as many of # them depend on one of the following contrib applications. 'auth': None, 'contenttypes': None, 'sessions': None, } log_config = copy.deepcopy(DEFAULT_LOGGING) # Filter out non-error logging so we don't have to capture it in lots of # tests. log_config['loggers']['django']['level'] = 'ERROR' settings.LOGGING = log_config settings.SILENCED_SYSTEM_CHECKS = [ 'fields.W342', # ForeignKey(unique=True) -> OneToOneField ] # Load all the ALWAYS_INSTALLED_APPS. django.setup() # It would be nice to put this validation earlier but it must come after # django.setup() so that connection.features.gis_enabled can be accessed # without raising AppRegistryNotReady when running gis_tests in isolation # on some backends (e.g. PostGIS). if 'gis_tests' in test_labels_set and not connection.features.gis_enabled: print('Aborting: A GIS database backend is required to run gis_tests.') sys.exit(1) # Load all the test model apps. test_modules = get_test_modules() installed_app_names = set(get_installed()) for modpath, module_name in test_modules: if modpath: module_label = modpath + '.' + module_name else: module_label = module_name # if the module (or an ancestor) was named on the command line, or # no modules were named (i.e., run all), import # this module and add it to INSTALLED_APPS. if not test_labels: module_found_in_labels = True else: module_found_in_labels = any( # exact match or ancestor match module_label == label or module_label.startswith(label + '.') for label in test_labels_set) if module_name in CONTRIB_TESTS_TO_APPS and module_found_in_labels: settings.INSTALLED_APPS.append(CONTRIB_TESTS_TO_APPS[module_name]) if module_found_in_labels and module_label not in installed_app_names: if verbosity >= 2: print("Importing application %s" % module_name) settings.INSTALLED_APPS.append(module_label) # Add contrib.gis to INSTALLED_APPS if needed (rather than requiring # @override_settings(INSTALLED_APPS=...) on all test cases. gis = 'django.contrib.gis' if connection.features.gis_enabled and gis not in settings.INSTALLED_APPS: if verbosity >= 2: print("Importing application %s" % gis) settings.INSTALLED_APPS.append(gis) apps.set_installed_apps(settings.INSTALLED_APPS) return state
parser.add_argument( '--reverse', action='store_true', help='Sort test suites and test cases in opposite order to debug ' 'test side effects not apparent with normal execution lineup.', ) parser.add_argument( '--selenium', dest='selenium', action=ActionSelenium, metavar='BROWSERS', help='A comma-separated list of browsers to run the Selenium tests against.', ) parser.add_argument( '--debug-sql', action='store_true', dest='debug_sql', help='Turn on the SQL query logger within tests.', ) parser.add_argument( '--parallel', dest='parallel', nargs='?', default=0, type=int, const=default_test_processes(), metavar='N', help='Run tests using up to N parallel processes.', ) parser.add_argument( '--tag', dest='tags', action='append', help='Run only tests with the specified tags. Can be used multiple times.', ) parser.add_argument( '--exclude-tag', dest='exclude_tags', action='append', help='Do not run tests with the specified tag. Can be used multiple times.', ) options = parser.parse_args() # Allow including a trailing slash on app_labels for tab completion convenience options.modules = [os.path.normpath(labels) for labels in options.modules]
def setup(verbosity, test_labels, parallel): # Reduce the given test labels to just the app module path. test_labels_set = set() for label in test_labels: bits = label.split('.')[:1] test_labels_set.add('.'.join(bits)) if verbosity >= 1: msg = "Testing against Django installed in '%s'" % os.path.dirname( django.__file__) max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += " with up to %d processes" % max_parallel print(msg) # Force declaring available_apps in TransactionTestCase for faster tests. def no_available_apps(self): raise Exception("Please define available_apps in TransactionTestCase " "and its subclasses.") TransactionTestCase.available_apps = property(no_available_apps) TestCase.available_apps = None state = { 'INSTALLED_APPS': settings.INSTALLED_APPS, 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), 'TEMPLATES': settings.TEMPLATES, 'LANGUAGE_CODE': settings.LANGUAGE_CODE, 'STATIC_URL': settings.STATIC_URL, 'STATIC_ROOT': settings.STATIC_ROOT, 'MIDDLEWARE': settings.MIDDLEWARE, } # Redirect some settings for the duration of these tests. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = 'tests.urls' settings.STATIC_URL = '/static/' settings.STATIC_ROOT = os.path.join(TMPDIR, 'static') settings.TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [TEMPLATE_DIR], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }] settings.LANGUAGE_CODE = 'en' settings.SITE_ID = 1 settings.MIDDLEWARE = ALWAYS_MIDDLEWARE settings.MIGRATION_MODULES = { # This lets us skip creating migrations for the test models as many of # them depend on one of the following contrib applications. 'auth': None, 'contenttypes': None, 'sessions': None, } log_config = copy.deepcopy(DEFAULT_LOGGING) # Filter out non-error logging so we don't have to capture it in lots of # tests. log_config['loggers']['django']['level'] = 'ERROR' settings.LOGGING = log_config settings.SILENCED_SYSTEM_CHECKS = [ 'fields.W342', # ForeignKey(unique=True) -> OneToOneField ] # Load all the ALWAYS_INSTALLED_APPS. django.setup() # Load all the test model apps. apps.set_installed_apps(settings.INSTALLED_APPS) return state
def setup(verbosity, test_labels, parallel): if verbosity >= 1: msg = "Testing against Django installed in '%s'" % os.path.dirname(django.__file__) max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += " with up to %d processes" % max_parallel print(msg) # Force declaring available_apps in TransactionTestCase for faster tests. def no_available_apps(self): raise Exception("Please define available_apps in TransactionTestCase " "and its subclasses.") TransactionTestCase.available_apps = property(no_available_apps) TestCase.available_apps = None state = { 'INSTALLED_APPS': settings.INSTALLED_APPS, 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), 'TEMPLATES': settings.TEMPLATES, 'LANGUAGE_CODE': settings.LANGUAGE_CODE, 'STATIC_URL': settings.STATIC_URL, 'STATIC_ROOT': settings.STATIC_ROOT, 'MIDDLEWARE_CLASSES': settings.MIDDLEWARE_CLASSES, } # Redirect some settings for the duration of these tests. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = 'urls' settings.STATIC_URL = '/static/' settings.STATIC_ROOT = os.path.join(TMPDIR, 'static') settings.TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [TEMPLATE_DIR], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }] settings.LANGUAGE_CODE = 'en' settings.SITE_ID = 1 settings.MIDDLEWARE_CLASSES = ALWAYS_MIDDLEWARE_CLASSES settings.MIGRATION_MODULES = { # these 'tests.migrations' modules don't actually exist, but this lets # us skip creating migrations for the test models. 'auth': 'django.contrib.auth.tests.migrations', 'contenttypes': 'contenttypes_tests.migrations', 'sessions': 'sessions_tests.migrations', } log_config = copy.deepcopy(DEFAULT_LOGGING) # Filter out non-error logging so we don't have to capture it in lots of # tests. log_config['loggers']['django']['level'] = 'ERROR' settings.LOGGING = log_config if verbosity > 0: # Ensure any warnings captured to logging are piped through a verbose # logging handler. If any -W options were passed explicitly on command # line, warnings are not captured, and this has no effect. logger = logging.getLogger('py.warnings') handler = logging.StreamHandler() logger.addHandler(handler) warnings.filterwarnings( 'ignore', 'The GeoManager class is deprecated.', RemovedInDjango20Warning ) # Load all the ALWAYS_INSTALLED_APPS. django.setup() # Load all the test model apps. test_modules = get_test_modules() # Reduce given test labels to just the app module path test_labels_set = set() for label in test_labels: bits = label.split('.')[:1] test_labels_set.add('.'.join(bits)) installed_app_names = set(get_installed()) for modpath, module_name in test_modules: if modpath: module_label = '.'.join([modpath, module_name]) else: module_label = module_name # if the module (or an ancestor) was named on the command line, or # no modules were named (i.e., run all), import # this module and add it to INSTALLED_APPS. if not test_labels: module_found_in_labels = True else: module_found_in_labels = any( # exact match or ancestor match module_label == label or module_label.startswith(label + '.') for label in test_labels_set) if module_name in CONTRIB_TESTS_TO_APPS and module_found_in_labels: settings.INSTALLED_APPS.append(CONTRIB_TESTS_TO_APPS[module_name]) if module_found_in_labels and module_label not in installed_app_names: if verbosity >= 2: print("Importing application %s" % module_name) settings.INSTALLED_APPS.append(module_label) # Add contrib.gis to INSTALLED_APPS if needed (rather than requiring # @override_settings(INSTALLED_APPS=...) on all test cases. gis = 'django.contrib.gis' if connection.features.gis_enabled and gis not in settings.INSTALLED_APPS: if verbosity >= 2: print("Importing application %s" % gis) settings.INSTALLED_APPS.append(gis) apps.set_installed_apps(settings.INSTALLED_APPS) return state
parser.add_argument('--reverse', action='store_true', default=False, help='Sort test suites and test cases in opposite order to debug ' 'test side effects not apparent with normal execution lineup.') parser.add_argument('--liveserver', help='Overrides the default address where the live server (used with ' 'LiveServerTestCase) is expected to run from. The default value ' 'is localhost:8081-8179.') parser.add_argument( '--selenium', action='store_true', dest='selenium', default=False, help='Run the Selenium tests as well (if Selenium is installed).') parser.add_argument( '--debug-sql', action='store_true', dest='debug_sql', default=False, help='Turn on the SQL query logger within tests.') parser.add_argument( '--parallel', dest='parallel', nargs='?', default=0, type=int, const=default_test_processes(), metavar='N', help='Run tests using up to N parallel processes.') options = parser.parse_args() # mock is a required dependency try: from django.test import mock # NOQA except ImportError: print( "Please install test dependencies first: \n" "$ pip install -r requirements/py%s.txt" % sys.version_info.major ) sys.exit(1) # Allow including a trailing slash on app_labels for tab completion convenience
def get_parser(): parser = argparse.ArgumentParser(description="Run the Django test suite.") parser.add_argument( 'modules', nargs='*', metavar='module', help='Optional path(s) to test modules; e.g. "i18n" or ' '"i18n.tests.TranslationTests.test_lazy_objects".', ) parser.add_argument( '-v', '--verbosity', default=1, type=int, choices=[0, 1, 2, 3], help='Verbosity level; 0=minimal output, 1=normal output, 2=all output', ) parser.add_argument( '--noinput', action='store_false', dest='interactive', help='Tells Django to NOT prompt the user for input of any kind.', ) parser.add_argument( '--failfast', action='store_true', help= 'Tells Django to stop running the test suite after first failed test.', ) parser.add_argument( '-k', '--keepdb', action='store_true', help='Tells Django to preserve the test database between runs.', ) parser.add_argument( '--settings', help='Python path to settings module, e.g. "myproject.settings". If ' 'this isn\'t provided, either the DJANGO_SETTINGS_MODULE ' 'environment variable or "test_sqlite" will be used.', ) parser.add_argument( '--bisect', help='Bisect the test suite to discover a test that causes a test ' 'failure when combined with the named test.', ) parser.add_argument( '--pair', help= 'Run the test suite in pairs with the named test to find problem pairs.', ) parser.add_argument( '--reverse', action='store_true', help='Sort test suites and test cases in opposite order to debug ' 'test side effects not apparent with normal execution lineup.', ) parser.add_argument( '--selenium', action=ActionSelenium, metavar='BROWSERS', help= 'A comma-separated list of browsers to run the Selenium tests against.', ) parser.add_argument( '--selenium-hub', help= 'A URL for a selenium hub instance to use in combination with --selenium.', ) parser.add_argument( '--external-host', default=socket.gethostname(), help= 'The external host that can be reached by the selenium hub instance when running Selenium ' 'tests via Selenium Hub.', ) parser.add_argument( '--debug-sql', action='store_true', help='Turn on the SQL query logger within tests.', ) parser.add_argument( '--parallel', nargs='?', default=0, type=int, const=default_test_processes(), metavar='N', help='Run tests using up to N parallel processes.', ) parser.add_argument( '--tag', dest='tags', action='append', help= 'Run only tests with the specified tags. Can be used multiple times.', ) parser.add_argument( '--exclude-tag', dest='exclude_tags', action='append', help= 'Do not run tests with the specified tag. Can be used multiple times.', ) return parser
parser.add_argument('--reverse', action='store_true', default=False, help='Sort test suites and test cases in opposite order to debug ' 'test side effects not apparent with normal execution lineup.') parser.add_argument('--liveserver', help='Overrides the default address where the live server (used with ' 'LiveServerTestCase) is expected to run from. The default value ' 'is localhost:8081-8179.') parser.add_argument( '--selenium', action='store_true', dest='selenium', default=False, help='Run the Selenium tests as well (if Selenium is installed).') parser.add_argument( '--debug-sql', action='store_true', dest='debug_sql', default=False, help='Turn on the SQL query logger within tests.') parser.add_argument( '--parallel', dest='parallel', nargs='?', default=0, type=int, const=default_test_processes(), help='Run tests in parallel processes.') options = parser.parse_args() # mock is a required dependency try: from django.test import mock # NOQA except ImportError: print( "Please install test dependencies first: \n" "$ pip install -r requirements/py%s.txt" % sys.version_info.major ) sys.exit(1) # Allow including a trailing slash on app_labels for tab completion convenience
def setup(verbosity, test_labels, parallel): if verbosity >= 1: msg = f"Testing against django-site-metrics installed in '{os.path.dirname(metrics.__file__)}'" max_parallel = default_test_processes() if parallel == 0 else parallel if max_parallel > 1: msg += f" with up to {max_parallel} processes" print(msg) # Force declaring available_apps in TransactionTestCase for faster tests. def no_available_apps(self): raise Exception( "Please define available_apps in TransactionTestCase and its subclasses." ) TransactionTestCase.available_apps = property(no_available_apps) TestCase.available_apps = None state = { "INSTALLED_APPS": settings.INSTALLED_APPS, "ROOT_URLCONF": getattr(settings, "ROOT_URLCONF", ""), "TEMPLATES": settings.TEMPLATES, "LANGUAGE_CODE": settings.LANGUAGE_CODE, "STATIC_URL": settings.STATIC_URL, "STATIC_ROOT": settings.STATIC_ROOT, "MIDDLEWARE": settings.MIDDLEWARE, } # Redirect some settings for the duration of these tests. settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = "urls" settings.STATIC_URL = "/static/" settings.STATIC_ROOT = os.path.join(TMPDIR, "static") settings.TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [TEMPLATE_DIR], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] settings.LANGUAGE_CODE = "en" settings.SITE_ID = 1 settings.MIDDLEWARE = ALWAYS_MIDDLEWARE settings.MIGRATION_MODULES = { # This lets us skip creating migrations for the test models as many of # them depend on one of the following contrib applications. "auth": None, "contenttypes": None, "sessions": None, } log_config = copy.deepcopy(DEFAULT_LOGGING) # Filter out non-error logging so we don't have to capture it in lots of # tests. log_config["loggers"]["django"]["level"] = "ERROR" settings.LOGGING = log_config settings.SILENCED_SYSTEM_CHECKS = [ "fields.W342", # ForeignKey(unique=True) -> OneToOneField ] # Load all the ALWAYS_INSTALLED_APPS. django.setup() # Load all the test model apps. test_modules = get_test_modules() # Reduce given test labels to just the app module path test_labels_set = set() for label in test_labels: bits = label.split(".")[:1] test_labels_set.add(".".join(bits)) installed_app_names = set(get_installed()) for modpath, module_name in test_modules: if modpath: module_label = ".".join([modpath, module_name]) else: module_label = module_name # if the module (or an ancestor) was named on the command line, or # no modules were named (i.e., run all), import # this module and add it to INSTALLED_APPS. if not test_labels: module_found_in_labels = True else: module_found_in_labels = any( # exact match or ancestor match module_label == label or module_label.startswith(label + ".") for label in test_labels_set) if module_found_in_labels and module_label not in installed_app_names: if verbosity >= 2: print(f"Importing application {module_name}") settings.INSTALLED_APPS.append(module_label) apps.set_installed_apps(settings.INSTALLED_APPS) return state