diff --git a/pytest_django/compat.py b/pytest_django/compat.py index 3baeea9a5..71f32fe4d 100644 --- a/pytest_django/compat.py +++ b/pytest_django/compat.py @@ -1,12 +1,17 @@ # This file cannot be imported from until Django sets up try: # Django 1.11 - from django.test.utils import setup_databases, teardown_databases # noqa + from django.test.utils import setup_databases, teardown_databases # noqa: F401 except ImportError: # In Django prior to 1.11, teardown_databases is only available as a method on DiscoverRunner - from django.test.runner import setup_databases, DiscoverRunner as _DiscoverRunner # noqa + from django.test.runner import ( # noqa: F401 + setup_databases, + DiscoverRunner as _DiscoverRunner, + ) def teardown_databases(db_cfg, verbosity): - (_DiscoverRunner(verbosity=verbosity, - interactive=False) - .teardown_databases(db_cfg)) + ( + _DiscoverRunner(verbosity=verbosity, interactive=False).teardown_databases( + db_cfg + ) + ) diff --git a/pytest_django/db_reuse.py b/pytest_django/db_reuse.py index a9962dae2..443869142 100644 --- a/pytest_django/db_reuse.py +++ b/pytest_django/db_reuse.py @@ -11,15 +11,15 @@ def test_database_exists_from_previous_run(connection): # When using a real SQLite backend (via TEST_NAME), check if the file # exists, because it gets created automatically. - if connection.settings_dict['ENGINE'] == 'django.db.backends.sqlite3': + if connection.settings_dict["ENGINE"] == "django.db.backends.sqlite3": if not os.path.exists(test_db_name): return False - orig_db_name = connection.settings_dict['NAME'] - connection.settings_dict['NAME'] = test_db_name + orig_db_name = connection.settings_dict["NAME"] + connection.settings_dict["NAME"] = test_db_name # With SQLite memory databases the db never exists. - if connection.settings_dict['NAME'] == ':memory:': + if connection.settings_dict["NAME"] == ":memory:": return False try: @@ -29,7 +29,7 @@ def test_database_exists_from_previous_run(connection): return False finally: connection.close() - connection.settings_dict['NAME'] = orig_db_name + connection.settings_dict["NAME"] = orig_db_name def _monkeypatch(obj, method_name, new_method): @@ -43,8 +43,9 @@ def _monkeypatch(obj, method_name, new_method): setattr(obj, method_name, wrapped_method) -def create_test_db_with_reuse(self, verbosity=1, autoclobber=False, - keepdb=False, serialize=False): +def create_test_db_with_reuse( + self, verbosity=1, autoclobber=False, keepdb=False, serialize=False +): """ This method is a monkey patched version of create_test_db that will not actually create a new database, but just reuse the @@ -53,14 +54,16 @@ def create_test_db_with_reuse(self, verbosity=1, autoclobber=False, This is only used with Django < 1.8. """ test_database_name = self._get_test_db_name() - self.connection.settings_dict['NAME'] = test_database_name + self.connection.settings_dict["NAME"] = test_database_name if verbosity >= 1: - test_db_repr = '' + test_db_repr = "" if verbosity >= 2: test_db_repr = " ('%s')" % test_database_name - print("Re-using existing test database for alias '%s'%s..." % ( - self.connection.alias, test_db_repr)) + print( + "Re-using existing test database for alias '%s'%s..." + % (self.connection.alias, test_db_repr) + ) return test_database_name @@ -70,5 +73,6 @@ def monkey_patch_creation_for_db_reuse(): for connection in connections.all(): if test_database_exists_from_previous_run(connection): - _monkeypatch(connection.creation, 'create_test_db', - create_test_db_with_reuse) + _monkeypatch( + connection.creation, "create_test_db", create_test_db_with_reuse + ) diff --git a/pytest_django/django_compat.py b/pytest_django/django_compat.py index fe026cf1b..18a2413e5 100644 --- a/pytest_django/django_compat.py +++ b/pytest_django/django_compat.py @@ -6,7 +6,7 @@ def is_django_unittest(request_or_item): """Returns True if the request_or_item is a Django test case, otherwise False""" from django.test import SimpleTestCase - cls = getattr(request_or_item, 'cls', None) + cls = getattr(request_or_item, "cls", None) if cls is None: return False diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index c3ffa6eab..c8bc0bb83 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -15,14 +15,26 @@ from .lazy_django import skip_if_no_django -__all__ = ['django_db_setup', 'db', 'transactional_db', 'django_db_reset_sequences', - 'admin_user', 'django_user_model', 'django_username_field', - 'client', 'admin_client', 'rf', 'settings', 'live_server', - '_live_server_helper', 'django_assert_num_queries', - 'django_assert_max_num_queries'] - - -@pytest.fixture(scope='session') +__all__ = [ + "django_db_setup", + "db", + "transactional_db", + "django_db_reset_sequences", + "admin_user", + "django_user_model", + "django_username_field", + "client", + "admin_client", + "rf", + "settings", + "live_server", + "_live_server_helper", + "django_assert_num_queries", + "django_assert_max_num_queries", +] + + +@pytest.fixture(scope="session") def django_db_modify_db_settings_xdist_suffix(request): skip_if_no_django() @@ -31,46 +43,46 @@ def django_db_modify_db_settings_xdist_suffix(request): for db_settings in settings.DATABASES.values(): try: - test_name = db_settings['TEST']['NAME'] + test_name = db_settings["TEST"]["NAME"] except KeyError: test_name = None if not test_name: - if db_settings['ENGINE'] == 'django.db.backends.sqlite3': - return ':memory:' + if db_settings["ENGINE"] == "django.db.backends.sqlite3": + return ":memory:" else: - test_name = 'test_{}'.format(db_settings['NAME']) + test_name = "test_{}".format(db_settings["NAME"]) # Put a suffix like _gw0, _gw1 etc on xdist processes - xdist_suffix = getattr(request.config, 'slaveinput', {}).get('slaveid') - if test_name != ':memory:' and xdist_suffix is not None: - test_name = '{}_{}'.format(test_name, xdist_suffix) + xdist_suffix = getattr(request.config, "slaveinput", {}).get("slaveid") + if test_name != ":memory:" and xdist_suffix is not None: + test_name = "{}_{}".format(test_name, xdist_suffix) - db_settings.setdefault('TEST', {}) - db_settings['TEST']['NAME'] = test_name + db_settings.setdefault("TEST", {}) + db_settings["TEST"]["NAME"] = test_name -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_modify_db_settings(django_db_modify_db_settings_xdist_suffix): skip_if_no_django() -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_use_migrations(request): - return not request.config.getvalue('nomigrations') + return not request.config.getvalue("nomigrations") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_keepdb(request): - return request.config.getvalue('reuse_db') + return request.config.getvalue("reuse_db") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_createdb(request): - return request.config.getvalue('create_db') + return request.config.getvalue("create_db") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_setup( request, django_test_environment, @@ -89,7 +101,7 @@ def django_db_setup( _disable_native_migrations() if django_db_keepdb and not django_db_createdb: - setup_databases_args['keepdb'] = True + setup_databases_args["keepdb"] = True with django_db_blocker.unblock(): db_cfg = setup_databases( @@ -100,21 +112,19 @@ def django_db_setup( def teardown_database(): with django_db_blocker.unblock(): - teardown_databases( - db_cfg, - verbosity=pytest.config.option.verbose, - ) + teardown_databases(db_cfg, verbosity=pytest.config.option.verbose) if not django_db_keepdb: request.addfinalizer(teardown_database) -def _django_db_fixture_helper(request, django_db_blocker, - transactional=False, reset_sequences=False): +def _django_db_fixture_helper( + request, django_db_blocker, transactional=False, reset_sequences=False +): if is_django_unittest(request): return - if not transactional and 'live_server' in request.funcargnames: + if not transactional and "live_server" in request.funcargnames: # Do nothing, we get called with transactional=True, too. return @@ -125,13 +135,15 @@ def _django_db_fixture_helper(request, django_db_blocker, from django.test import TransactionTestCase as django_case if reset_sequences: + class ResetSequenceTestCase(django_case): reset_sequences = True + django_case = ResetSequenceTestCase else: from django.test import TestCase as django_case - test_case = django_case(methodName='__init__') + test_case = django_case(methodName="__init__") test_case._pre_setup() request.addfinalizer(test_case._post_teardown) @@ -145,7 +157,8 @@ def _disable_native_migrations(): # ############### User visible fixtures ################ -@pytest.fixture(scope='function') + +@pytest.fixture(scope="function") def db(request, django_db_setup, django_db_blocker): """Require a django test database. @@ -160,16 +173,18 @@ def db(request, django_db_setup, django_db_blocker): over each other in the following order (the last one wins): ``db``, ``transactional_db``, ``django_db_reset_sequences``. """ - if 'django_db_reset_sequences' in request.funcargnames: - request.getfixturevalue('django_db_reset_sequences') - if 'transactional_db' in request.funcargnames \ - or 'live_server' in request.funcargnames: - request.getfixturevalue('transactional_db') + if "django_db_reset_sequences" in request.funcargnames: + request.getfixturevalue("django_db_reset_sequences") + if ( + "transactional_db" in request.funcargnames + or "live_server" in request.funcargnames + ): + request.getfixturevalue("transactional_db") else: _django_db_fixture_helper(request, django_db_blocker, transactional=False) -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def transactional_db(request, django_db_setup, django_db_blocker): """Require a django test database with transaction support. @@ -183,13 +198,12 @@ def transactional_db(request, django_db_setup, django_db_blocker): over each other in the following order (the last one wins): ``db``, ``transactional_db``, ``django_db_reset_sequences``. """ - if 'django_db_reset_sequences' in request.funcargnames: - request.getfixturevalue('django_db_reset_sequences') - _django_db_fixture_helper(request, django_db_blocker, - transactional=True) + if "django_db_reset_sequences" in request.funcargnames: + request.getfixturevalue("django_db_reset_sequences") + _django_db_fixture_helper(request, django_db_blocker, transactional=True) -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def django_db_reset_sequences(request, django_db_setup, django_db_blocker): """Require a transactional test database with sequence reset support. @@ -202,8 +216,9 @@ def django_db_reset_sequences(request, django_db_setup, django_db_blocker): over each other in the following order (the last one wins): ``db``, ``transactional_db``, ``django_db_reset_sequences``. """ - _django_db_fixture_helper(request, django_db_blocker, - transactional=True, reset_sequences=True) + _django_db_fixture_helper( + request, django_db_blocker, transactional=True, reset_sequences=True + ) @pytest.fixture() @@ -220,6 +235,7 @@ def client(): def django_user_model(db): """The class of Django's user model.""" from django.contrib.auth import get_user_model + return get_user_model() @@ -240,13 +256,14 @@ def admin_user(db, django_user_model, django_username_field): username_field = django_username_field try: - user = UserModel._default_manager.get(**{username_field: 'admin'}) + user = UserModel._default_manager.get(**{username_field: "admin"}) except UserModel.DoesNotExist: extra_fields = {} - if username_field != 'username': - extra_fields[username_field] = 'admin' + if username_field != "username": + extra_fields[username_field] = "admin" user = UserModel._default_manager.create_superuser( - 'admin', 'admin@example.com', 'password', **extra_fields) + "admin", "admin@example.com", "password", **extra_fields + ) return user @@ -256,7 +273,7 @@ def admin_client(db, admin_user): from django.test.client import Client client = Client() - client.login(username=admin_user.username, password='password') + client.login(username=admin_user.username, password="password") return client @@ -275,23 +292,25 @@ class SettingsWrapper(object): def __delattr__(self, attr): from django.test import override_settings + override = override_settings() override.enable() from django.conf import settings + delattr(settings, attr) self._to_restore.append(override) def __setattr__(self, attr, value): from django.test import override_settings - override = override_settings(**{ - attr: value - }) + + override = override_settings(**{attr: value}) override.enable() self._to_restore.append(override) def __getattr__(self, item): from django.conf import settings + return getattr(settings, item) def finalize(self): @@ -311,7 +330,7 @@ def settings(): wrapper.finalize() -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def live_server(request): """Run a live Django server in the background during tests @@ -335,30 +354,33 @@ def live_server(request): import django - addr = (request.config.getvalue('liveserver') or - os.getenv('DJANGO_LIVE_TEST_SERVER_ADDRESS')) + addr = request.config.getvalue("liveserver") or os.getenv( + "DJANGO_LIVE_TEST_SERVER_ADDRESS" + ) - if addr and ':' in addr: + if addr and ":" in addr: if django.VERSION >= (1, 11): - ports = addr.split(':')[1] - if '-' in ports or ',' in ports: - request.config.warn('D001', - 'Specifying multiple live server ports is not supported ' - 'in Django 1.11. This will be an error in a future ' - 'pytest-django release.') + ports = addr.split(":")[1] + if "-" in ports or "," in ports: + request.config.warn( + "D001", + "Specifying multiple live server ports is not supported " + "in Django 1.11. This will be an error in a future " + "pytest-django release.", + ) if not addr: if django.VERSION < (1, 11): - addr = 'localhost:8081,8100-8200' + addr = "localhost:8081,8100-8200" else: - addr = 'localhost' + addr = "localhost" server = live_server_helper.LiveServer(addr) request.addfinalizer(server.stop) return server -@pytest.fixture(autouse=True, scope='function') +@pytest.fixture(autouse=True, scope="function") def _live_server_helper(request): """Helper to make live_server work, internal to pytest-django. @@ -374,12 +396,12 @@ def _live_server_helper(request): It will also override settings only for the duration of the test. """ - if 'live_server' not in request.funcargnames: + if "live_server" not in request.funcargnames: return - request.getfixturevalue('transactional_db') + request.getfixturevalue("transactional_db") - live_server = request.getfixturevalue('live_server') + live_server = request.getfixturevalue("live_server") live_server._live_server_modified_settings.enable() request.addfinalizer(live_server._live_server_modified_settings.disable) @@ -391,7 +413,7 @@ def _assert_num_queries(config, num, exact=True, connection=None): if connection is None: from django.db import connection - verbose = config.getoption('verbose') > 0 + verbose = config.getoption("verbose") > 0 with CaptureQueriesContext(connection) as context: yield context num_queries = len(context) @@ -399,24 +421,24 @@ def _assert_num_queries(config, num, exact=True, connection=None): if failed: msg = "Expected to perform {} queries {}{}".format( num, - '' if exact else 'or less ', - 'but {} done'.format( - num_queries == 1 and '1 was' or '%d were' % (num_queries,) - ) + "" if exact else "or less ", + "but {} done".format( + num_queries == 1 and "1 was" or "%d were" % (num_queries,) + ), ) if verbose: - sqls = (q['sql'] for q in context.captured_queries) - msg += '\n\nQueries:\n========\n\n%s' % '\n\n'.join(sqls) + sqls = (q["sql"] for q in context.captured_queries) + msg += "\n\nQueries:\n========\n\n%s" % "\n\n".join(sqls) else: msg += " (add -v option to show queries)" pytest.fail(msg) -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def django_assert_num_queries(pytestconfig): return partial(_assert_num_queries, pytestconfig) -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def django_assert_max_num_queries(pytestconfig): return partial(_assert_num_queries, pytestconfig, exact=False) diff --git a/pytest_django/lazy_django.py b/pytest_django/lazy_django.py index e1f47d141..b2d49bc70 100644 --- a/pytest_django/lazy_django.py +++ b/pytest_django/lazy_django.py @@ -11,13 +11,15 @@ def skip_if_no_django(): """Raises a skip exception when no Django settings are available""" if not django_settings_is_configured(): - pytest.skip('no Django settings') + pytest.skip("no Django settings") def django_settings_is_configured(): # Avoid importing Django if it has not yet been imported - if not os.environ.get('DJANGO_SETTINGS_MODULE') \ - and 'django.conf' not in sys.modules: + if ( + not os.environ.get("DJANGO_SETTINGS_MODULE") + and "django.conf" not in sys.modules + ): return False # If DJANGO_SETTINGS_MODULE is defined at this point, Django is assumed to @@ -26,4 +28,4 @@ def django_settings_is_configured(): def get_django_version(): - return __import__('django').VERSION + return __import__("django").VERSION diff --git a/pytest_django/live_server_helper.py b/pytest_django/live_server_helper.py index ac5605fb1..3a5dd084e 100644 --- a/pytest_django/live_server_helper.py +++ b/pytest_django/live_server_helper.py @@ -18,36 +18,40 @@ def __init__(self, addr): for conn in connections.all(): # If using in-memory sqlite databases, pass the connections to # the server thread. - if (conn.settings_dict['ENGINE'] == 'django.db.backends.sqlite3' and - conn.settings_dict['NAME'] == ':memory:'): + if ( + conn.settings_dict["ENGINE"] == "django.db.backends.sqlite3" + and conn.settings_dict["NAME"] == ":memory:" + ): # Explicitly enable thread-shareability for this connection conn.allow_thread_sharing = True connections_override[conn.alias] = conn - liveserver_kwargs = {'connections_override': connections_override} + liveserver_kwargs = {"connections_override": connections_override} from django.conf import settings - if 'django.contrib.staticfiles' in settings.INSTALLED_APPS: + + if "django.contrib.staticfiles" in settings.INSTALLED_APPS: from django.contrib.staticfiles.handlers import StaticFilesHandler - liveserver_kwargs['static_handler'] = StaticFilesHandler + + liveserver_kwargs["static_handler"] = StaticFilesHandler else: from django.test.testcases import _StaticFilesHandler - liveserver_kwargs['static_handler'] = _StaticFilesHandler + + liveserver_kwargs["static_handler"] = _StaticFilesHandler if django.VERSION < (1, 11): host, possible_ports = parse_addr(addr) - self.thread = LiveServerThread(host, possible_ports, - **liveserver_kwargs) + self.thread = LiveServerThread(host, possible_ports, **liveserver_kwargs) else: try: - host, port = addr.split(':') + host, port = addr.split(":") except ValueError: host = addr else: - liveserver_kwargs['port'] = int(port) + liveserver_kwargs["port"] = int(port) self.thread = LiveServerThread(host, **liveserver_kwargs) self._live_server_modified_settings = modify_settings( - ALLOWED_HOSTS={'append': host}, + ALLOWED_HOSTS={"append": host} ) self.thread.daemon = True @@ -64,15 +68,18 @@ def stop(self): @property def url(self): - return 'http://%s:%s' % (self.thread.host, self.thread.port) + return "http://%s:%s" % (self.thread.host, self.thread.port) if sys.version_info < (3, 0): + def __unicode__(self): return self.url def __add__(self, other): return unicode(self) + other # noqa: pyflakes on python3 + else: + def __str__(self): return self.url @@ -80,7 +87,7 @@ def __add__(self, other): return str(self) + other def __repr__(self): - return '' % self.url + return "" % self.url def parse_addr(specified_address): @@ -93,10 +100,10 @@ def parse_addr(specified_address): # it down into a detailed list of all possible ports. possible_ports = [] try: - host, port_ranges = specified_address.split(':') - for port_range in port_ranges.split(','): + host, port_ranges = specified_address.split(":") + for port_range in port_ranges.split(","): # A port range can be of either form: '8000' or '8000-8010'. - extremes = list(map(int, port_range.split('-'))) + extremes = list(map(int, port_range.split("-"))) assert len(extremes) in (1, 2) if len(extremes) == 1: # Port range of the form '8000' @@ -106,7 +113,6 @@ def parse_addr(specified_address): for port in range(extremes[0], extremes[1] + 1): possible_ports.append(port) except Exception: - raise Exception( - 'Invalid address ("%s") for live server.' % specified_address) + raise Exception('Invalid address ("%s") for live server.' % specified_address) return host, possible_ports diff --git a/pytest_django/migrations.py b/pytest_django/migrations.py index ce80bbe1e..3c39cb9f6 100644 --- a/pytest_django/migrations.py +++ b/pytest_django/migrations.py @@ -3,7 +3,6 @@ class DisableMigrations(object): - def __init__(self): self._django_version = get_django_version() @@ -14,4 +13,4 @@ def __getitem__(self, item): if self._django_version >= (1, 9): return None else: - return 'notmigrations' + return "notmigrations" diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 9b9e7c79e..249fbad6e 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -43,69 +43,117 @@ import pathlib2 as pathlib -SETTINGS_MODULE_ENV = 'DJANGO_SETTINGS_MODULE' -CONFIGURATION_ENV = 'DJANGO_CONFIGURATION' -INVALID_TEMPLATE_VARS_ENV = 'FAIL_INVALID_TEMPLATE_VARS' +SETTINGS_MODULE_ENV = "DJANGO_SETTINGS_MODULE" +CONFIGURATION_ENV = "DJANGO_CONFIGURATION" +INVALID_TEMPLATE_VARS_ENV = "FAIL_INVALID_TEMPLATE_VARS" PY2 = sys.version_info[0] == 2 # ############### pytest hooks ################ + def pytest_addoption(parser): - group = parser.getgroup('django') - group._addoption('--reuse-db', - action='store_true', dest='reuse_db', default=False, - help='Re-use the testing database if it already exists, ' - 'and do not remove it when the test finishes.') - group._addoption('--create-db', - action='store_true', dest='create_db', default=False, - help='Re-create the database, even if it exists. This ' - 'option can be used to override --reuse-db.') - group._addoption('--ds', - action='store', type=str, dest='ds', default=None, - help='Set DJANGO_SETTINGS_MODULE.') - group._addoption('--dc', - action='store', type=str, dest='dc', default=None, - help='Set DJANGO_CONFIGURATION.') - group._addoption('--nomigrations', '--no-migrations', - action='store_true', dest='nomigrations', default=False, - help='Disable Django migrations on test setup') - group._addoption('--migrations', - action='store_false', dest='nomigrations', default=False, - help='Enable Django migrations on test setup') - parser.addini(CONFIGURATION_ENV, - 'django-configurations class to use by pytest-django.') - group._addoption('--liveserver', default=None, - help='Address and port for the live_server fixture.') - parser.addini(SETTINGS_MODULE_ENV, - 'Django settings module to use by pytest-django.') - - parser.addini('django_find_project', - 'Automatically find and add a Django project to the ' - 'Python path.', - type='bool', default=True) - group._addoption('--fail-on-template-vars', - action='store_true', dest='itv', default=False, - help='Fail for invalid variables in templates.') - parser.addini(INVALID_TEMPLATE_VARS_ENV, - 'Fail for invalid variables in templates.', - type='bool', default=False) - - -PROJECT_FOUND = ('pytest-django found a Django project in %s ' - '(it contains manage.py) and added it to the Python path.\n' - 'If this is wrong, add "django_find_project = false" to ' - 'pytest.ini and explicitly manage your Python path.') - -PROJECT_NOT_FOUND = ('pytest-django could not find a Django project ' - '(no manage.py file could be found). You must ' - 'explicitly add your Django project to the Python path ' - 'to have it picked up.') - -PROJECT_SCAN_DISABLED = ('pytest-django did not search for Django ' - 'projects since it is disabled in the configuration ' - '("django_find_project = false")') + group = parser.getgroup("django") + group._addoption( + "--reuse-db", + action="store_true", + dest="reuse_db", + default=False, + help="Re-use the testing database if it already exists, " + "and do not remove it when the test finishes.", + ) + group._addoption( + "--create-db", + action="store_true", + dest="create_db", + default=False, + help="Re-create the database, even if it exists. This " + "option can be used to override --reuse-db.", + ) + group._addoption( + "--ds", + action="store", + type=str, + dest="ds", + default=None, + help="Set DJANGO_SETTINGS_MODULE.", + ) + group._addoption( + "--dc", + action="store", + type=str, + dest="dc", + default=None, + help="Set DJANGO_CONFIGURATION.", + ) + group._addoption( + "--nomigrations", + "--no-migrations", + action="store_true", + dest="nomigrations", + default=False, + help="Disable Django migrations on test setup", + ) + group._addoption( + "--migrations", + action="store_false", + dest="nomigrations", + default=False, + help="Enable Django migrations on test setup", + ) + parser.addini( + CONFIGURATION_ENV, "django-configurations class to use by pytest-django." + ) + group._addoption( + "--liveserver", + default=None, + help="Address and port for the live_server fixture.", + ) + parser.addini( + SETTINGS_MODULE_ENV, "Django settings module to use by pytest-django." + ) + + parser.addini( + "django_find_project", + "Automatically find and add a Django project to the " "Python path.", + type="bool", + default=True, + ) + group._addoption( + "--fail-on-template-vars", + action="store_true", + dest="itv", + default=False, + help="Fail for invalid variables in templates.", + ) + parser.addini( + INVALID_TEMPLATE_VARS_ENV, + "Fail for invalid variables in templates.", + type="bool", + default=False, + ) + + +PROJECT_FOUND = ( + "pytest-django found a Django project in %s " + "(it contains manage.py) and added it to the Python path.\n" + 'If this is wrong, add "django_find_project = false" to ' + "pytest.ini and explicitly manage your Python path." +) + +PROJECT_NOT_FOUND = ( + "pytest-django could not find a Django project " + "(no manage.py file could be found). You must " + "explicitly add your Django project to the Python path " + "to have it picked up." +) + +PROJECT_SCAN_DISABLED = ( + "pytest-django did not search for Django " + "projects since it is disabled in the configuration " + '("django_find_project = false")' +) @contextlib.contextmanager @@ -113,7 +161,7 @@ def _handle_import_error(extra_message): try: yield except ImportError as e: - django_msg = (e.args[0] + '\n\n') if e.args else '' + django_msg = (e.args[0] + "\n\n") if e.args else "" msg = django_msg + extra_message raise ImportError(msg) @@ -121,7 +169,7 @@ def _handle_import_error(extra_message): def _add_django_project_to_path(args): def is_django_project(path): try: - return path.is_dir() and (path / 'manage.py').exists() + return path.is_dir() and (path / "manage.py").exists() except OSError: return False @@ -153,7 +201,7 @@ def find_django_path(args): def _setup_django(): - if 'django' not in sys.modules: + if "django" not in sys.modules: return import django.conf @@ -163,6 +211,7 @@ def _setup_django(): return import django.apps + if not django.apps.apps.ready: django.setup() @@ -174,36 +223,37 @@ def _get_boolean_value(x, name, default=None): return default if x in (True, False): return x - possible_values = {'true': True, - 'false': False, - '1': True, - '0': False} + possible_values = {"true": True, "false": False, "1": True, "0": False} try: return possible_values[x.lower()] except KeyError: - raise ValueError('{} is not a valid value for {}. ' - 'It must be one of {}.' - % (x, name, ', '.join(possible_values.keys()))) + raise ValueError( + "{} is not a valid value for {}. " + "It must be one of {}." % (x, name, ", ".join(possible_values.keys())) + ) def pytest_load_initial_conftests(early_config, parser, args): # Register the marks early_config.addinivalue_line( - 'markers', - 'django_db(transaction=False): Mark the test as using ' - 'the django test database. The *transaction* argument marks will ' + "markers", + "django_db(transaction=False): Mark the test as using " + "the django test database. The *transaction* argument marks will " "allow you to use real transactions in the test like Django's " - 'TransactionTestCase.') + "TransactionTestCase.", + ) early_config.addinivalue_line( - 'markers', - 'urls(modstr): Use a different URLconf for this test, similar to ' - 'the `urls` attribute of Django `TestCase` objects. *modstr* is ' - 'a string specifying the module of a URL config, e.g. ' - '"my_app.test_urls".') + "markers", + "urls(modstr): Use a different URLconf for this test, similar to " + "the `urls` attribute of Django `TestCase` objects. *modstr* is " + "a string specifying the module of a URL config, e.g. " + '"my_app.test_urls".', + ) early_config.addinivalue_line( - 'markers', - 'ignore_template_errors(): ignore errors from invalid template ' - 'variables (if --fail-on-template-vars is used).') + "markers", + "ignore_template_errors(): ignore errors from invalid template " + "variables (if --fail-on-template-vars is used).", + ) options = parser.parse_known_args(args) @@ -211,43 +261,51 @@ def pytest_load_initial_conftests(early_config, parser, args): return django_find_project = _get_boolean_value( - early_config.getini('django_find_project'), 'django_find_project') + early_config.getini("django_find_project"), "django_find_project" + ) if django_find_project: _django_project_scan_outcome = _add_django_project_to_path(args) else: _django_project_scan_outcome = PROJECT_SCAN_DISABLED - if (options.itv or - _get_boolean_value(os.environ.get(INVALID_TEMPLATE_VARS_ENV), - INVALID_TEMPLATE_VARS_ENV) or - early_config.getini(INVALID_TEMPLATE_VARS_ENV)): - os.environ[INVALID_TEMPLATE_VARS_ENV] = 'true' + if ( + options.itv + or _get_boolean_value( + os.environ.get(INVALID_TEMPLATE_VARS_ENV), INVALID_TEMPLATE_VARS_ENV + ) + or early_config.getini(INVALID_TEMPLATE_VARS_ENV) + ): + os.environ[INVALID_TEMPLATE_VARS_ENV] = "true" # Configure DJANGO_SETTINGS_MODULE if options.ds: - ds_source = 'command line option' + ds_source = "command line option" ds = options.ds elif SETTINGS_MODULE_ENV in os.environ: ds = os.environ[SETTINGS_MODULE_ENV] - ds_source = 'environment variable' + ds_source = "environment variable" elif early_config.getini(SETTINGS_MODULE_ENV): ds = early_config.getini(SETTINGS_MODULE_ENV) - ds_source = 'ini file' + ds_source = "ini file" else: ds = None ds_source = None if ds: - early_config._dsm_report_header = 'Django settings: %s (from %s)' % ( - ds, ds_source) + early_config._dsm_report_header = "Django settings: %s (from %s)" % ( + ds, + ds_source, + ) else: early_config._dsm_report_header = None # Configure DJANGO_CONFIGURATION - dc = (options.dc or - os.environ.get(CONFIGURATION_ENV) or - early_config.getini(CONFIGURATION_ENV)) + dc = ( + options.dc + or os.environ.get(CONFIGURATION_ENV) + or early_config.getini(CONFIGURATION_ENV) + ) if ds: os.environ[SETTINGS_MODULE_ENV] = ds @@ -257,6 +315,7 @@ def pytest_load_initial_conftests(early_config, parser, args): # Install the django-configurations importer import configurations.importer + configurations.importer.install() # Forcefully load Django settings, throws ImportError or @@ -290,18 +349,21 @@ def _classmethod_is_defined_at_leaf(cls, method_name): break assert super_method is not None, ( - '%s could not be found in base classes' % method_name) + "%s could not be found in base classes" % method_name + ) method = getattr(cls, method_name) try: f = method.__func__ except AttributeError: - pytest.fail('%s.%s should be a classmethod' % (cls, method_name)) - if PY2 and not (inspect.ismethod(method) and - inspect.isclass(method.__self__) and - issubclass(cls, method.__self__)): - pytest.fail('%s.%s should be a classmethod' % (cls, method_name)) + pytest.fail("%s.%s should be a classmethod" % (cls, method_name)) + if PY2 and not ( + inspect.ismethod(method) + and inspect.isclass(method.__self__) + and issubclass(cls, method.__self__) + ): + pytest.fail("%s.%s should be a classmethod" % (cls, method_name)) return f is not super_method.__func__ @@ -315,10 +377,10 @@ def _disable_class_methods(cls): _disabled_classmethods[cls] = ( # Get the classmethod object (not the resulting bound method), # otherwise inheritance will be broken when restoring. - cls.__dict__.get('setUpClass'), - _classmethod_is_defined_at_leaf(cls, 'setUpClass'), - cls.__dict__.get('tearDownClass'), - _classmethod_is_defined_at_leaf(cls, 'tearDownClass'), + cls.__dict__.get("setUpClass"), + _classmethod_is_defined_at_leaf(cls, "setUpClass"), + cls.__dict__.get("tearDownClass"), + _classmethod_is_defined_at_leaf(cls, "tearDownClass"), ) cls.setUpClass = types.MethodType(lambda cls: None, cls) @@ -326,10 +388,12 @@ def _disable_class_methods(cls): def _restore_class_methods(cls): - (setUpClass, - restore_setUpClass, - tearDownClass, - restore_tearDownClass) = _disabled_classmethods.pop(cls) + ( + setUpClass, + restore_setUpClass, + tearDownClass, + restore_tearDownClass, + ) = _disabled_classmethods.pop(cls) try: del cls.setUpClass @@ -354,7 +418,7 @@ def pytest_runtest_setup(item): _disable_class_methods(cls) -@pytest.fixture(autouse=True, scope='session') +@pytest.fixture(autouse=True, scope="session") def django_test_environment(request): """ Ensure that Django is loaded and has its testing environment setup. @@ -369,14 +433,14 @@ def django_test_environment(request): if django_settings_is_configured(): _setup_django() from django.conf import settings as dj_settings - from django.test.utils import (setup_test_environment, - teardown_test_environment) + from django.test.utils import setup_test_environment, teardown_test_environment + dj_settings.DEBUG = False setup_test_environment() request.addfinalizer(teardown_test_environment) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_blocker(): """Wrapper around Django's database access. @@ -403,23 +467,23 @@ def _django_db_marker(request): This will dynamically request the ``db``, ``transactional_db`` or ``django_db_reset_sequences`` fixtures as required by the django_db marker. """ - marker = request.node.get_closest_marker('django_db') + marker = request.node.get_closest_marker("django_db") if marker: transaction, reset_sequences = validate_django_db(marker) if reset_sequences: - request.getfixturevalue('django_db_reset_sequences') + request.getfixturevalue("django_db_reset_sequences") elif transaction: - request.getfixturevalue('transactional_db') + request.getfixturevalue("transactional_db") else: - request.getfixturevalue('db') + request.getfixturevalue("db") -@pytest.fixture(autouse=True, scope='class') +@pytest.fixture(autouse=True, scope="class") def _django_setup_unittest(request, django_db_blocker): """Setup a django unittest, internal to pytest-django.""" if django_settings_is_configured() and is_django_unittest(request): - request.getfixturevalue('django_test_environment') - request.getfixturevalue('django_db_setup') + request.getfixturevalue("django_test_environment") + request.getfixturevalue("django_db_setup") django_db_blocker.unblock() @@ -429,9 +493,9 @@ def _django_setup_unittest(request, django_db_blocker): # see pytest-dev/pytest-django#406 def _cleaning_debug(self): testMethod = getattr(self, self._testMethodName) - skipped = ( - getattr(self.__class__, "__unittest_skip__", False) or - getattr(testMethod, "__unittest_skip__", False)) + skipped = getattr(self.__class__, "__unittest_skip__", False) or getattr( + testMethod, "__unittest_skip__", False + ) if not skipped: self._pre_setup() @@ -453,42 +517,46 @@ def teardown(): request.addfinalizer(teardown) -@pytest.fixture(scope='function', autouse=True) +@pytest.fixture(scope="function", autouse=True) def _dj_autoclear_mailbox(): if not django_settings_is_configured(): return from django.core import mail + del mail.outbox[:] -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def mailoutbox(monkeypatch, django_mail_patch_dns, _dj_autoclear_mailbox): if not django_settings_is_configured(): return from django.core import mail + return mail.outbox -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def django_mail_patch_dns(monkeypatch, django_mail_dnsname): from django.core import mail - monkeypatch.setattr(mail.message, 'DNS_NAME', django_mail_dnsname) + monkeypatch.setattr(mail.message, "DNS_NAME", django_mail_dnsname) -@pytest.fixture(scope='function') + +@pytest.fixture(scope="function") def django_mail_dnsname(monkeypatch): - return 'fake-tests.example.com' + return "fake-tests.example.com" -@pytest.fixture(autouse=True, scope='function') +@pytest.fixture(autouse=True, scope="function") def _django_set_urlconf(request): """Apply the @pytest.mark.urls marker, internal to pytest-django.""" - marker = request.node.get_closest_marker('urls') + marker = request.node.get_closest_marker("urls") if marker: skip_if_no_django() import django.conf + try: from django.urls import clear_url_caches, set_urlconf except ImportError: @@ -511,7 +579,7 @@ def restore(): request.addfinalizer(restore) -@pytest.fixture(autouse=True, scope='session') +@pytest.fixture(autouse=True, scope="session") def _fail_for_invalid_template_variable(request): """Fixture that fails for invalid variables in templates. @@ -525,6 +593,7 @@ def _fail_for_invalid_template_variable(request): This behavior can be switched off using the marker: ``pytest.mark.ignore_template_errors`` """ + class InvalidVarException(object): """Custom handler for invalid strings in templates.""" @@ -533,7 +602,7 @@ def __init__(self): def __contains__(self, key): """There is a test for '%s' in TEMPLATE_STRING_IF_INVALID.""" - return key == '%s' + return key == "%s" @staticmethod def _get_origin(): @@ -543,10 +612,10 @@ def _get_origin(): # TEMPLATE_DEBUG).. for f in stack[2:]: func = f[3] - if func == 'render': + if func == "render": frame = f[0] try: - origin = frame.f_locals['self'].origin + origin = frame.f_locals["self"].origin except (AttributeError, KeyError): continue if origin is not None: @@ -556,18 +625,16 @@ def _get_origin(): # finding the ``render`` needle in the stack frame = reduce( - lambda x, y: y[3] == 'render' and 'base.py' in y[1] and y or x, - stack + lambda x, y: y[3] == "render" and "base.py" in y[1] and y or x, stack ) # assert 0, stack frame = frame[0] # finding only the frame locals in all frame members f_locals = reduce( - lambda x, y: y[0] == 'f_locals' and y or x, - inspect.getmembers(frame) + lambda x, y: y[0] == "f_locals" and y or x, inspect.getmembers(frame) )[1] # ``django.template.base.Template`` - template = f_locals['self'] + template = f_locals["self"] if isinstance(template, Template): return template.name @@ -575,8 +642,7 @@ def __mod__(self, var): """Handle TEMPLATE_STRING_IF_INVALID % var.""" origin = self._get_origin() if origin: - msg = "Undefined template variable '%s' in '%s'" % ( - var, origin) + msg = "Undefined template variable '%s' in '%s'" % (var, origin) else: msg = "Undefined template variable '%s'" % var if self.fail: @@ -584,13 +650,16 @@ def __mod__(self, var): else: return msg - if (os.environ.get(INVALID_TEMPLATE_VARS_ENV, 'false') == 'true' and - django_settings_is_configured()): + if ( + os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true" + and django_settings_is_configured() + ): from django.conf import settings as dj_settings if dj_settings.TEMPLATES: - dj_settings.TEMPLATES[0]['OPTIONS']['string_if_invalid'] = ( - InvalidVarException()) + dj_settings.TEMPLATES[0]["OPTIONS"][ + "string_if_invalid" + ] = InvalidVarException() else: dj_settings.TEMPLATE_STRING_IF_INVALID = InvalidVarException() @@ -599,18 +668,18 @@ def __mod__(self, var): def _template_string_if_invalid_marker(request): """Apply the @pytest.mark.ignore_template_errors marker, internal to pytest-django.""" - marker = request.keywords.get('ignore_template_errors', None) - if os.environ.get(INVALID_TEMPLATE_VARS_ENV, 'false') == 'true': + marker = request.keywords.get("ignore_template_errors", None) + if os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true": if marker and django_settings_is_configured(): from django.conf import settings as dj_settings if dj_settings.TEMPLATES: - dj_settings.TEMPLATES[0]['OPTIONS']['string_if_invalid'].fail = False + dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"].fail = False else: dj_settings.TEMPLATE_STRING_IF_INVALID.fail = False -@pytest.fixture(autouse=True, scope='function') +@pytest.fixture(autouse=True, scope="function") def _django_clear_site_cache(): """Clears ``django.contrib.sites.models.SITE_CACHE`` to avoid unexpected behavior with cached site objects. @@ -619,10 +688,12 @@ def _django_clear_site_cache(): if django_settings_is_configured(): from django.conf import settings as dj_settings - if 'django.contrib.sites' in dj_settings.INSTALLED_APPS: + if "django.contrib.sites" in dj_settings.INSTALLED_APPS: from django.contrib.sites.models import Site + Site.objects.clear_cache() + # ############### Helper Functions ################ @@ -664,9 +735,11 @@ def _save_active_wrapper(self): def _blocking_wrapper(*args, **kwargs): __tracebackhide__ = True __tracebackhide__ # Silence pyflakes - pytest.fail('Database access not allowed, ' - 'use the "django_db" mark, or the ' - '"db" or "transactional_db" fixtures to enable it.') + pytest.fail( + "Database access not allowed, " + 'use the "django_db" mark, or the ' + '"db" or "transactional_db" fixtures to enable it.' + ) def unblock(self): """Enable access to the Django database.""" @@ -696,8 +769,10 @@ def validate_django_db(marker): A sequence reset is only allowed when combined with a transaction. """ + def apifun(transaction=False, reset_sequences=False): return transaction, reset_sequences + return apifun(*marker.args, **marker.kwargs) @@ -707,6 +782,8 @@ def validate_urls(marker): It checks the signature and creates the `urls` attribute on the marker which will have the correct value. """ + def apifun(urls): return urls + return apifun(*marker.args, **marker.kwargs) diff --git a/pytest_django_test/db_helpers.py b/pytest_django_test/db_helpers.py index 719f12f95..de21e2a0e 100644 --- a/pytest_django_test/db_helpers.py +++ b/pytest_django_test/db_helpers.py @@ -66,14 +66,14 @@ def drop_database(name=TEST_DB_NAME, suffix=None): if get_db_engine() == 'postgresql_psycopg2': r = run_cmd('psql', 'postgres', '-c', 'DROP DATABASE %s' % name) - assert ('DROP DATABASE' in force_text(r.std_out) or - 'does not exist' in force_text(r.std_err)) + assert "DROP DATABASE" in force_text( + r.std_out + ) or "does not exist" in force_text(r.std_err) return if get_db_engine() == 'mysql': r = run_mysql('-e', 'DROP DATABASE %s' % name) - assert ('database doesn\'t exist' in force_text(r.std_err) or - r.status_code == 0) + assert "database doesn't exist" in force_text(r.std_err) or r.status_code == 0 return if get_db_engine() == 'sqlite3': diff --git a/setup.cfg b/setup.cfg index a007b53fb..a26f8c40b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,10 +9,8 @@ testpaths = tests universal = 1 [flake8] -# Ref: https://flake8.readthedocs.io/en/latest/warnings.html#error-codes -ignore = NONE -# Default, if empty: -# ignore = E123,E133,E226,E241,E242 +# W503 line break before binary operator +ignore = W503 max-line-length = 99 exclude = lib/,src/,docs/,bin/ diff --git a/tests/conftest.py b/tests/conftest.py index 15c6e55c7..c770d7510 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,47 +13,47 @@ except ImportError: import pathlib2 as pathlib -pytest_plugins = 'pytester' +pytest_plugins = "pytester" REPOSITORY_ROOT = pathlib.Path(__file__).parent def pytest_configure(config): config.addinivalue_line( - 'markers', - 'django_project: options for the django_testdir fixture') + "markers", "django_project: options for the django_testdir fixture" + ) -def _marker_apifun(extra_settings='', - create_manage_py=False, - project_root=None): +def _marker_apifun(extra_settings="", create_manage_py=False, project_root=None): return { - 'extra_settings': extra_settings, - 'create_manage_py': create_manage_py, - 'project_root': project_root, + "extra_settings": extra_settings, + "create_manage_py": create_manage_py, + "project_root": project_root, } @pytest.fixture def testdir(testdir, monkeypatch): - monkeypatch.delenv('PYTEST_ADDOPTS', raising=False) + monkeypatch.delenv("PYTEST_ADDOPTS", raising=False) return testdir -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def django_testdir(request, testdir, monkeypatch): - marker = request.node.get_closest_marker('django_project') + marker = request.node.get_closest_marker("django_project") options = _marker_apifun(**(marker.kwargs if marker else {})) - if hasattr(request.node.cls, 'db_settings'): + if hasattr(request.node.cls, "db_settings"): db_settings = request.node.cls.db_settings else: db_settings = copy.deepcopy(settings.DATABASES) - db_settings['default']['NAME'] = DB_NAME - db_settings['default']['TEST']['NAME'] = TEST_DB_NAME + db_settings["default"]["NAME"] = DB_NAME + db_settings["default"]["TEST"]["NAME"] = TEST_DB_NAME - test_settings = dedent(''' + test_settings = ( + dedent( + """ import django # Pypy compatibility @@ -94,33 +94,36 @@ def django_testdir(request, testdir, monkeypatch): ] %(extra_settings)s - ''') % { - 'db_settings': repr(db_settings), - 'extra_settings': dedent(options['extra_settings'])} - - if options['project_root']: - project_root = testdir.mkdir(options['project_root']) + """ + ) + % { + "db_settings": repr(db_settings), + "extra_settings": dedent(options["extra_settings"]), + } + ) + + if options["project_root"]: + project_root = testdir.mkdir(options["project_root"]) else: project_root = testdir.tmpdir - tpkg_path = project_root.mkdir('tpkg') + tpkg_path = project_root.mkdir("tpkg") - if options['create_manage_py']: - project_root.ensure('manage.py') + if options["create_manage_py"]: + project_root.ensure("manage.py") - tpkg_path.ensure('__init__.py') + tpkg_path.ensure("__init__.py") - app_source = REPOSITORY_ROOT / '../pytest_django_test/app' - test_app_path = tpkg_path.join('app') + app_source = REPOSITORY_ROOT / "../pytest_django_test/app" + test_app_path = tpkg_path.join("app") # Copy the test app to make it available in the new test run - shutil.copytree(six.text_type(app_source), - six.text_type(test_app_path)) + shutil.copytree(six.text_type(app_source), six.text_type(test_app_path)) tpkg_path.join("the_settings.py").write(test_settings) - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.the_settings') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.the_settings") - def create_test_module(test_code, filename='test_the_test.py'): + def create_test_module(test_code, filename="test_the_test.py"): r = tpkg_path.join(filename) r.write(dedent(test_code), ensure=True) return r @@ -134,11 +137,13 @@ def create_app_file(code, filename): testdir.create_app_file = create_app_file testdir.project_root = project_root - testdir.makeini(""" + testdir.makeini( + """ [pytest] addopts = --strict console_output_style=classic - """) + """ + ) return testdir @@ -146,12 +151,15 @@ def create_app_file(code, filename): @pytest.fixture def django_testdir_initial(django_testdir): """A django_testdir fixture which provides initial_data.""" - django_testdir.project_root.join('tpkg/app/migrations').remove() - django_testdir.makefile('.json', initial_data=""" + django_testdir.project_root.join("tpkg/app/migrations").remove() + django_testdir.makefile( + ".json", + initial_data=""" [{ "pk": 1, "model": "app.item", "fields": { "name": "mark_initial_data" } - }]""") + }]""", + ) return django_testdir diff --git a/tests/test_database.py b/tests/test_database.py index 0ce8eac3e..607aadf47 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -9,13 +9,15 @@ def db_supports_reset_sequences(): """Return if the current db engine supports `reset_sequences`.""" - return (connection.features.supports_transactions and - connection.features.supports_sequence_reset) + return ( + connection.features.supports_transactions + and connection.features.supports_sequence_reset + ) def test_noaccess(): with pytest.raises(pytest.fail.Exception): - Item.objects.create(name='spam') + Item.objects.create(name="spam") with pytest.raises(pytest.fail.Exception): Item.objects.count() @@ -23,7 +25,7 @@ def test_noaccess(): @pytest.fixture def noaccess(): with pytest.raises(pytest.fail.Exception): - Item.objects.create(name='spam') + Item.objects.create(name="spam") with pytest.raises(pytest.fail.Exception): Item.objects.count() @@ -39,8 +41,8 @@ def non_zero_sequences_counter(db): This is used to test the `reset_sequences` feature. """ - item_1 = Item.objects.create(name='item_1') - item_2 = Item.objects.create(name='item_2') + item_1 = Item.objects.create(name="item_1") + item_2 = Item.objects.create(name="item_2") item_1.delete() item_2.delete() @@ -48,17 +50,17 @@ def non_zero_sequences_counter(db): class TestDatabaseFixtures: """Tests for the different database fixtures.""" - @pytest.fixture(params=['db', 'transactional_db', 'django_db_reset_sequences']) + @pytest.fixture(params=["db", "transactional_db", "django_db_reset_sequences"]) def all_dbs(self, request): - if request.param == 'django_db_reset_sequences': - return request.getfixturevalue('django_db_reset_sequences') - elif request.param == 'transactional_db': - return request.getfixturevalue('transactional_db') - elif request.param == 'db': - return request.getfixturevalue('db') + if request.param == "django_db_reset_sequences": + return request.getfixturevalue("django_db_reset_sequences") + elif request.param == "transactional_db": + return request.getfixturevalue("transactional_db") + elif request.param == "db": + return request.getfixturevalue("db") def test_access(self, all_dbs): - Item.objects.create(name='spam') + Item.objects.create(name="spam") def test_clean_db(self, all_dbs): # Relies on the order: test_access created an object @@ -66,33 +68,36 @@ def test_clean_db(self, all_dbs): def test_transactions_disabled(self, db): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert connection.in_atomic_block def test_transactions_enabled(self, transactional_db): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert not connection.in_atomic_block - def test_transactions_enabled_via_reset_seq( - self, django_db_reset_sequences): + def test_transactions_enabled_via_reset_seq(self, django_db_reset_sequences): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert not connection.in_atomic_block def test_django_db_reset_sequences_fixture( - self, db, django_testdir, non_zero_sequences_counter): + self, db, django_testdir, non_zero_sequences_counter + ): if not db_supports_reset_sequences(): - pytest.skip('transactions and reset_sequences must be supported ' - 'by the database to run this test') + pytest.skip( + "transactions and reset_sequences must be supported " + "by the database to run this test" + ) # The test runs on a database that already contains objects, so its # id counter is > 1. We check for the ids of newly created objects. - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest from .app.models import Item @@ -100,24 +105,25 @@ def test_django_db_reset_sequences_requested( django_db_reset_sequences): item = Item.objects.create(name='new_item') assert item.id == 1 - ''') + """ + ) - result = django_testdir.runpytest_subprocess('-v', '--reuse-db') - result.stdout.fnmatch_lines([ - "*test_django_db_reset_sequences_requested PASSED*", - ]) + result = django_testdir.runpytest_subprocess("-v", "--reuse-db") + result.stdout.fnmatch_lines( + ["*test_django_db_reset_sequences_requested PASSED*"] + ) @pytest.fixture def mydb(self, all_dbs): # This fixture must be able to access the database - Item.objects.create(name='spam') + Item.objects.create(name="spam") def test_mydb(self, mydb): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") # Check the fixture had access to the db - item = Item.objects.get(name='spam') + item = Item.objects.get(name="spam") assert item def test_fixture_clean(self, all_dbs): @@ -128,7 +134,7 @@ def test_fixture_clean(self, all_dbs): @pytest.fixture def fin(self, request, all_dbs): # This finalizer must be able to access the database - request.addfinalizer(lambda: Item.objects.create(name='spam')) + request.addfinalizer(lambda: Item.objects.create(name="spam")) def test_fin(self, fin): # Check finalizer has db access (teardown will fail if not) @@ -138,15 +144,15 @@ def test_fin(self, fin): class TestDatabaseFixturesAllOrder: @pytest.fixture def fixture_with_db(self, db): - Item.objects.create(name='spam') + Item.objects.create(name="spam") @pytest.fixture def fixture_with_transdb(self, transactional_db): - Item.objects.create(name='spam') + Item.objects.create(name="spam") @pytest.fixture def fixture_with_reset_sequences(self, django_db_reset_sequences): - Item.objects.create(name='spam') + Item.objects.create(name="spam") def test_trans(self, fixture_with_transdb): pass @@ -160,8 +166,9 @@ def test_db_trans(self, fixture_with_db, fixture_with_transdb): def test_trans_db(self, fixture_with_transdb, fixture_with_db): pass - def test_reset_sequences(self, fixture_with_reset_sequences, - fixture_with_transdb, fixture_with_db): + def test_reset_sequences( + self, fixture_with_reset_sequences, fixture_with_transdb, fixture_with_db + ): pass @@ -170,7 +177,7 @@ class TestDatabaseMarker: @pytest.mark.django_db def test_access(self): - Item.objects.create(name='spam') + Item.objects.create(name="spam") @pytest.mark.django_db def test_clean_db(self): @@ -180,39 +187,40 @@ def test_clean_db(self): @pytest.mark.django_db def test_transactions_disabled(self): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert connection.in_atomic_block @pytest.mark.django_db(transaction=False) def test_transactions_disabled_explicit(self): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert connection.in_atomic_block @pytest.mark.django_db(transaction=True) def test_transactions_enabled(self): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert not connection.in_atomic_block @pytest.mark.django_db def test_reset_sequences_disabled(self, request): - marker = request.node.get_closest_marker('django_db') + marker = request.node.get_closest_marker("django_db") assert not marker.kwargs @pytest.mark.django_db(reset_sequences=True) def test_reset_sequences_enabled(self, request): - marker = request.node.get_closest_marker('django_db') - assert marker.kwargs['reset_sequences'] + marker = request.node.get_closest_marker("django_db") + assert marker.kwargs["reset_sequences"] def test_unittest_interaction(django_testdir): "Test that (non-Django) unittests cannot access the DB." - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest import unittest from .app.models import Item @@ -236,42 +244,53 @@ def test_db_access_2(self): class TestCase(unittest.TestCase): def test_db_access_3(self): Item.objects.count() == 1 - ''') - - result = django_testdir.runpytest_subprocess('-v', '--reuse-db') - result.stdout.fnmatch_lines([ - "*test_db_access_1 ERROR*", - "*test_db_access_2 FAILED*", - "*test_db_access_3 FAILED*", - "*ERROR at setup of TestCase_setupClass.test_db_access_1*", - '*Failed: Database access not allowed, use the "django_db" mark, ' - 'or the "db" or "transactional_db" fixtures to enable it.', - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v", "--reuse-db") + result.stdout.fnmatch_lines( + [ + "*test_db_access_1 ERROR*", + "*test_db_access_2 FAILED*", + "*test_db_access_3 FAILED*", + "*ERROR at setup of TestCase_setupClass.test_db_access_1*", + '*Failed: Database access not allowed, use the "django_db" mark, ' + 'or the "db" or "transactional_db" fixtures to enable it.', + ] + ) class Test_database_blocking: def test_db_access_in_conftest(self, django_testdir): """Make sure database access in conftest module is prohibited.""" - django_testdir.makeconftest(""" + django_testdir.makeconftest( + """ from tpkg.app.models import Item Item.objects.get() - """) + """ + ) - result = django_testdir.runpytest_subprocess('-v') - result.stderr.fnmatch_lines([ - '*Failed: Database access not allowed, use the "django_db" mark, ' - 'or the "db" or "transactional_db" fixtures to enable it.*', - ]) + result = django_testdir.runpytest_subprocess("-v") + result.stderr.fnmatch_lines( + [ + '*Failed: Database access not allowed, use the "django_db" mark, ' + 'or the "db" or "transactional_db" fixtures to enable it.*' + ] + ) def test_db_access_in_test_module(self, django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ from tpkg.app.models import Item Item.objects.get() - """) - - result = django_testdir.runpytest_subprocess('-v') - result.stdout.fnmatch_lines([ - '*Failed: Database access not allowed, use the "django_db" mark, ' - 'or the "db" or "transactional_db" fixtures to enable it.', - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v") + result.stdout.fnmatch_lines( + [ + '*Failed: Database access not allowed, use the "django_db" mark, ' + 'or the "db" or "transactional_db" fixtures to enable it.' + ] + ) diff --git a/tests/test_db_setup.py b/tests/test_db_setup.py index 331ba4f7f..7d54283b4 100644 --- a/tests/test_db_setup.py +++ b/tests/test_db_setup.py @@ -1,14 +1,19 @@ import pytest from pytest_django.lazy_django import get_django_version -from pytest_django_test.db_helpers import (db_exists, drop_database, - mark_database, mark_exists, - skip_if_sqlite_in_memory) +from pytest_django_test.db_helpers import ( + db_exists, + drop_database, + mark_database, + mark_exists, + skip_if_sqlite_in_memory, +) def test_db_reuse_simple(django_testdir): "A test for all backends to check that `--reuse-db` works." - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest from .app.models import Item @@ -16,13 +21,12 @@ def test_db_reuse_simple(django_testdir): @pytest.mark.django_db def test_db_can_be_accessed(): assert Item.objects.count() == 0 - ''') + """ + ) - result = django_testdir.runpytest_subprocess('-v', '--reuse-db') + result = django_testdir.runpytest_subprocess("-v", "--reuse-db") assert result.ret == 0 - result.stdout.fnmatch_lines([ - "*test_db_can_be_accessed PASSED*", - ]) + result.stdout.fnmatch_lines(["*test_db_can_be_accessed PASSED*"]) def test_db_reuse(django_testdir): @@ -31,7 +35,8 @@ def test_db_reuse(django_testdir): """ skip_if_sqlite_in_memory() - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest from .app.models import Item @@ -39,7 +44,8 @@ def test_db_reuse(django_testdir): @pytest.mark.django_db def test_db_can_be_accessed(): assert Item.objects.count() == 0 - ''') + """ + ) # Use --create-db on the first run to make sure we are not just re-using a # database from another test run @@ -48,31 +54,27 @@ def test_db_can_be_accessed(): # Do not pass in --create-db to make sure it is created when it # does not exist - result_first = django_testdir.runpytest_subprocess('-v', '--reuse-db') + result_first = django_testdir.runpytest_subprocess("-v", "--reuse-db") assert result_first.ret == 0 - result_first.stdout.fnmatch_lines([ - "*test_db_can_be_accessed PASSED*", - ]) + result_first.stdout.fnmatch_lines(["*test_db_can_be_accessed PASSED*"]) assert not mark_exists() mark_database() assert mark_exists() - result_second = django_testdir.runpytest_subprocess('-v', '--reuse-db') + result_second = django_testdir.runpytest_subprocess("-v", "--reuse-db") assert result_second.ret == 0 - result_second.stdout.fnmatch_lines([ - "*test_db_can_be_accessed PASSED*", - ]) + result_second.stdout.fnmatch_lines(["*test_db_can_be_accessed PASSED*"]) # Make sure the database has not been re-created assert mark_exists() - result_third = django_testdir.runpytest_subprocess('-v', '--reuse-db', '--create-db') + result_third = django_testdir.runpytest_subprocess( + "-v", "--reuse-db", "--create-db" + ) assert result_third.ret == 0 - result_third.stdout.fnmatch_lines([ - "*test_db_can_be_accessed PASSED*", - ]) + result_third.stdout.fnmatch_lines(["*test_db_can_be_accessed PASSED*"]) # Make sure the database has been re-created and the mark is gone assert db_exists() @@ -81,17 +83,18 @@ def test_db_can_be_accessed(): class TestSqlite: - db_settings = {'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'db_name', - 'TEST': { - 'NAME': 'test_custom_db_name' + db_settings = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "db_name", + "TEST": {"NAME": "test_custom_db_name"}, } - }} + } def test_sqlite_test_name_used(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest from django.db import connections from django import VERSION @@ -103,20 +106,22 @@ def test_a(): assert conn.vendor == 'sqlite' print(conn.settings_dict) assert conn.settings_dict['NAME'] == 'test_custom_db_name' - ''') + """ + ) - result = django_testdir.runpytest_subprocess('--tb=short', '-v') + result = django_testdir.runpytest_subprocess("--tb=short", "-v") assert result.ret == 0 - result.stdout.fnmatch_lines(['*test_a*PASSED*']) + result.stdout.fnmatch_lines(["*test_a*PASSED*"]) def test_xdist_with_reuse(django_testdir): skip_if_sqlite_in_memory() - drop_database('gw0') - drop_database('gw1') + drop_database("gw0") + drop_database("gw1") - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest from .app.models import Item @@ -147,44 +152,49 @@ def test_c(settings): @pytest.mark.django_db def test_d(settings): _check(settings) - ''') + """ + ) - result = django_testdir.runpytest_subprocess('-vv', '-n2', '-s', '--reuse-db') + result = django_testdir.runpytest_subprocess("-vv", "-n2", "-s", "--reuse-db") assert result.ret == 0 - result.stdout.fnmatch_lines(['*PASSED*test_a*']) - result.stdout.fnmatch_lines(['*PASSED*test_b*']) - result.stdout.fnmatch_lines(['*PASSED*test_c*']) - result.stdout.fnmatch_lines(['*PASSED*test_d*']) + result.stdout.fnmatch_lines(["*PASSED*test_a*"]) + result.stdout.fnmatch_lines(["*PASSED*test_b*"]) + result.stdout.fnmatch_lines(["*PASSED*test_c*"]) + result.stdout.fnmatch_lines(["*PASSED*test_d*"]) - assert db_exists('gw0') - assert db_exists('gw1') + assert db_exists("gw0") + assert db_exists("gw1") - result = django_testdir.runpytest_subprocess('-vv', '-n2', '-s', '--reuse-db') + result = django_testdir.runpytest_subprocess("-vv", "-n2", "-s", "--reuse-db") assert result.ret == 0 - result.stdout.fnmatch_lines(['*PASSED*test_a*']) - result.stdout.fnmatch_lines(['*PASSED*test_b*']) - result.stdout.fnmatch_lines(['*PASSED*test_c*']) - result.stdout.fnmatch_lines(['*PASSED*test_d*']) - - result = django_testdir.runpytest_subprocess('-vv', '-n2', '-s', '--reuse-db', - '--create-db') + result.stdout.fnmatch_lines(["*PASSED*test_a*"]) + result.stdout.fnmatch_lines(["*PASSED*test_b*"]) + result.stdout.fnmatch_lines(["*PASSED*test_c*"]) + result.stdout.fnmatch_lines(["*PASSED*test_d*"]) + + result = django_testdir.runpytest_subprocess( + "-vv", "-n2", "-s", "--reuse-db", "--create-db" + ) assert result.ret == 0 - result.stdout.fnmatch_lines(['*PASSED*test_a*']) - result.stdout.fnmatch_lines(['*PASSED*test_b*']) - result.stdout.fnmatch_lines(['*PASSED*test_c*']) - result.stdout.fnmatch_lines(['*PASSED*test_d*']) + result.stdout.fnmatch_lines(["*PASSED*test_a*"]) + result.stdout.fnmatch_lines(["*PASSED*test_b*"]) + result.stdout.fnmatch_lines(["*PASSED*test_c*"]) + result.stdout.fnmatch_lines(["*PASSED*test_d*"]) class TestSqliteWithXdist: - db_settings = {'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': '/tmp/should-not-be-used', - }} + db_settings = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "/tmp/should-not-be-used", + } + } def test_sqlite_in_memory_used(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest from django.db import connections @@ -195,19 +205,24 @@ def test_a(): assert conn.vendor == 'sqlite' db_name = conn.creation._get_test_db_name() assert 'file:memorydb' in db_name or db_name == ':memory:' - ''') + """ + ) - result = django_testdir.runpytest_subprocess('--tb=short', '-vv', '-n1') + result = django_testdir.runpytest_subprocess("--tb=short", "-vv", "-n1") assert result.ret == 0 - result.stdout.fnmatch_lines(['*PASSED*test_a*']) + result.stdout.fnmatch_lines(["*PASSED*test_a*"]) -@pytest.mark.skipif(get_django_version() >= (1, 9), - reason=('Django 1.9 requires migration and has no concept ' - 'of initial data fixtures')) +@pytest.mark.skipif( + get_django_version() >= (1, 9), + reason=( + "Django 1.9 requires migration and has no concept " "of initial data fixtures" + ), +) def test_initial_data(django_testdir_initial): """Test that initial data gets loaded.""" - django_testdir_initial.create_test_module(''' + django_testdir_initial.create_test_module( + """ import pytest from .app.models import Item @@ -216,44 +231,56 @@ def test_initial_data(django_testdir_initial): def test_inner(): assert [x.name for x in Item.objects.all()] \ == ["mark_initial_data"] - ''') + """ + ) - result = django_testdir_initial.runpytest_subprocess('--tb=short', '-v') + result = django_testdir_initial.runpytest_subprocess("--tb=short", "-v") assert result.ret == 0 - result.stdout.fnmatch_lines(['*test_inner*PASSED*']) + result.stdout.fnmatch_lines(["*test_inner*PASSED*"]) class TestNativeMigrations(object): """ Tests for Django Migrations """ def test_no_migrations(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest @pytest.mark.django_db def test_inner_migrations(): pass - ''') + """ + ) - migration_file = django_testdir.project_root.join("tpkg/app/migrations/0001_initial.py") + migration_file = django_testdir.project_root.join( + "tpkg/app/migrations/0001_initial.py" + ) assert migration_file.isfile() - migration_file.write('raise Exception("This should not get imported.")', ensure=True) + migration_file.write( + 'raise Exception("This should not get imported.")', ensure=True + ) - result = django_testdir.runpytest_subprocess('--nomigrations', '--tb=short', '-v') + result = django_testdir.runpytest_subprocess( + "--nomigrations", "--tb=short", "-v" + ) assert result.ret == 0 - result.stdout.fnmatch_lines(['*test_inner_migrations*PASSED*']) + result.stdout.fnmatch_lines(["*test_inner_migrations*PASSED*"]) def test_migrations_run(self, django_testdir): testdir = django_testdir - testdir.create_test_module(''' + testdir.create_test_module( + """ import pytest @pytest.mark.django_db def test_inner_migrations(): pass - ''') + """ + ) - testdir.create_app_file(""" + testdir.create_app_file( + """ from django.db import migrations, models def print_it(apps, schema_editor): @@ -280,12 +307,15 @@ class Migration(migrations.Migration): print_it, ), ] - """, 'migrations/0001_initial.py') - result = testdir.runpytest_subprocess('--tb=short', '-v', '-s') + """, + "migrations/0001_initial.py", + ) + result = testdir.runpytest_subprocess("--tb=short", "-v", "-s") assert result.ret == 0 - result.stdout.fnmatch_lines(['*mark_migrations_run*']) + result.stdout.fnmatch_lines(["*mark_migrations_run*"]) - result = testdir.runpytest_subprocess('--no-migrations', '--migrations', - '--tb=short', '-v', '-s') + result = testdir.runpytest_subprocess( + "--no-migrations", "--migrations", "--tb=short", "-v", "-s" + ) assert result.ret == 0 - result.stdout.fnmatch_lines(['*mark_migrations_run*']) + result.stdout.fnmatch_lines(["*mark_migrations_run*"]) diff --git a/tests/test_django_configurations.py b/tests/test_django_configurations.py index 42c56875f..a7aa7a982 100644 --- a/tests/test_django_configurations.py +++ b/tests/test_django_configurations.py @@ -4,17 +4,20 @@ """ import pytest -pytest.importorskip('configurations') +pytest.importorskip("configurations") try: import configurations.importer + configurations except ImportError as e: - if 'LaxOptionParser' in e.args[0]: - pytest.skip('This version of django-configurations is incompatible with Django: ' # noqa - 'https://github.com/jezdez/django-configurations/issues/65') # noqa + if "LaxOptionParser" in e.args[0]: + pytest.skip( + "This version of django-configurations is incompatible with Django: " # noqa + "https://github.com/jezdez/django-configurations/issues/65" + ) # noqa -BARE_SETTINGS = ''' +BARE_SETTINGS = """ from configurations import Configuration class MySettings(Configuration): @@ -27,71 +30,81 @@ class MySettings(Configuration): } SECRET_KEY = 'foobar' -''' +""" def test_dc_env(testdir, monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.settings_env') - monkeypatch.setenv('DJANGO_CONFIGURATION', 'MySettings') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.settings_env") + monkeypatch.setenv("DJANGO_CONFIGURATION", "MySettings") - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_env.py') + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_env.py") settings.write(BARE_SETTINGS) - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_settings(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_env' assert os.environ['DJANGO_CONFIGURATION'] == 'MySettings' - """) + """ + ) result = testdir.runpytest_subprocess() - result.stdout.fnmatch_lines(['*1 passed*']) + result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 def test_dc_ini(testdir, monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.settings_env') - monkeypatch.setenv('DJANGO_CONFIGURATION', 'MySettings') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.settings_env") + monkeypatch.setenv("DJANGO_CONFIGURATION", "MySettings") - testdir.makeini(""" + testdir.makeini( + """ [pytest] DJANGO_SETTINGS_MODULE = DO_NOT_USE_ini DJANGO_CONFIGURATION = DO_NOT_USE_ini - """) - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_env.py') + """ + ) + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_env.py") settings.write(BARE_SETTINGS) - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_ds(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_env' assert os.environ['DJANGO_CONFIGURATION'] == 'MySettings' - """) + """ + ) result = testdir.runpytest_subprocess() - result.stdout.fnmatch_lines(['*1 passed*']) + result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 def test_dc_option(testdir, monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DO_NOT_USE_env') - monkeypatch.setenv('DJANGO_CONFIGURATION', 'DO_NOT_USE_env') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "DO_NOT_USE_env") + monkeypatch.setenv("DJANGO_CONFIGURATION", "DO_NOT_USE_env") - testdir.makeini(""" + testdir.makeini( + """ [pytest] DJANGO_SETTINGS_MODULE = DO_NOT_USE_ini DJANGO_CONFIGURATION = DO_NOT_USE_ini - """) - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_opt.py') + """ + ) + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_opt.py") settings.write(BARE_SETTINGS) - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_ds(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_opt' assert os.environ['DJANGO_CONFIGURATION'] == 'MySettings' - """) - result = testdir.runpytest_subprocess('--ds=tpkg.settings_opt', '--dc=MySettings') - result.stdout.fnmatch_lines(['*1 passed*']) + """ + ) + result = testdir.runpytest_subprocess("--ds=tpkg.settings_opt", "--dc=MySettings") + result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 diff --git a/tests/test_django_settings_module.py b/tests/test_django_settings_module.py index 5934bf285..3caff32cd 100644 --- a/tests/test_django_settings_module.py +++ b/tests/test_django_settings_module.py @@ -7,7 +7,7 @@ import pytest -BARE_SETTINGS = ''' +BARE_SETTINGS = """ # At least one database must be configured DATABASES = { 'default': { @@ -16,86 +16,103 @@ }, } SECRET_KEY = 'foobar' -''' +""" def test_ds_ini(testdir, monkeypatch): - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') - testdir.makeini(""" + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") + testdir.makeini( + """ [pytest] DJANGO_SETTINGS_MODULE = tpkg.settings_ini - """) - pkg = testdir.mkpydir('tpkg') - pkg.join('settings_ini.py').write(BARE_SETTINGS) - testdir.makepyfile(""" + """ + ) + pkg = testdir.mkpydir("tpkg") + pkg.join("settings_ini.py").write(BARE_SETTINGS) + testdir.makepyfile( + """ import os def test_ds(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_ini' - """) + """ + ) result = testdir.runpytest_subprocess() - assert result.parseoutcomes()['passed'] == 1 - result.stdout.fnmatch_lines(['Django settings: tpkg.settings_ini ' - '(from ini file)*']) + assert result.parseoutcomes()["passed"] == 1 + result.stdout.fnmatch_lines( + ["Django settings: tpkg.settings_ini " "(from ini file)*"] + ) assert result.ret == 0 def test_ds_env(testdir, monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.settings_env') - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_env.py') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.settings_env") + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_env.py") settings.write(BARE_SETTINGS) - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_settings(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_env' - """) + """ + ) result = testdir.runpytest_subprocess() - result.stdout.fnmatch_lines(['Django settings: tpkg.settings_env (from ' - 'environment variable)*']) - assert result.parseoutcomes()['passed'] == 1 + result.stdout.fnmatch_lines( + ["Django settings: tpkg.settings_env (from " "environment variable)*"] + ) + assert result.parseoutcomes()["passed"] == 1 def test_ds_option(testdir, monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DO_NOT_USE_env') - testdir.makeini(""" + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "DO_NOT_USE_env") + testdir.makeini( + """ [pytest] DJANGO_SETTINGS_MODULE = DO_NOT_USE_ini - """) - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_opt.py') + """ + ) + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_opt.py") settings.write(BARE_SETTINGS) - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_ds(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_opt' - """) - result = testdir.runpytest_subprocess('--ds=tpkg.settings_opt') - result.stdout.fnmatch_lines(['Django settings: tpkg.settings_opt ' - '(from command line option)']) - assert result.parseoutcomes()['passed'] == 1 + """ + ) + result = testdir.runpytest_subprocess("--ds=tpkg.settings_opt") + result.stdout.fnmatch_lines( + ["Django settings: tpkg.settings_opt " "(from command line option)"] + ) + assert result.parseoutcomes()["passed"] == 1 def test_ds_env_override_ini(testdir, monkeypatch): "DSM env should override ini." - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.settings_env') - testdir.makeini("""\ + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.settings_env") + testdir.makeini( + """\ [pytest] DJANGO_SETTINGS_MODULE = DO_NOT_USE_ini - """) - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_env.py') + """ + ) + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_env.py") settings.write(BARE_SETTINGS) - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_ds(): assert os.environ['DJANGO_SETTINGS_MODULE'] == 'tpkg.settings_env' - """) + """ + ) result = testdir.runpytest_subprocess() - assert result.parseoutcomes()['passed'] == 1 + assert result.parseoutcomes()["passed"] == 1 assert result.ret == 0 @@ -104,8 +121,8 @@ def test_ds_non_existent(testdir, monkeypatch): Make sure we do not fail with INTERNALERROR if an incorrect DJANGO_SETTINGS_MODULE is given. """ - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DOES_NOT_EXIST') - testdir.makepyfile('def test_ds(): pass') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "DOES_NOT_EXIST") + testdir.makepyfile("def test_ds(): pass") result = testdir.runpytest_subprocess() result.stderr.fnmatch_lines(["*ImportError:*DOES_NOT_EXIST*"]) assert result.ret != 0 @@ -116,21 +133,22 @@ def test_ds_after_user_conftest(testdir, monkeypatch): Test that the settings module can be imported, after pytest has adjusted the sys.path. """ - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'settings_after_conftest') - testdir.makepyfile('def test_ds(): pass') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "settings_after_conftest") + testdir.makepyfile("def test_ds(): pass") testdir.makepyfile(settings_after_conftest="SECRET_KEY='secret'") # testdir.makeconftest("import sys; print(sys.path)") - result = testdir.runpytest_subprocess('-v') - result.stdout.fnmatch_lines(['*1 passed*']) + result = testdir.runpytest_subprocess("-v") + result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 def test_ds_in_pytest_configure(testdir, monkeypatch): - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') - pkg = testdir.mkpydir('tpkg') - settings = pkg.join('settings_ds.py') + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") + pkg = testdir.mkpydir("tpkg") + settings = pkg.join("settings_ds.py") settings.write(BARE_SETTINGS) - testdir.makeconftest(""" + testdir.makeconftest( + """ import os from django.conf import settings @@ -139,15 +157,18 @@ def pytest_configure(): if not settings.configured: os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tpkg.settings_ds') - """) + """ + ) - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_anything(): pass - """) + """ + ) r = testdir.runpytest_subprocess() - assert r.parseoutcomes()['passed'] == 1 + assert r.parseoutcomes()["passed"] == 1 assert r.ret == 0 @@ -157,9 +178,10 @@ def test_django_settings_configure(testdir, monkeypatch): DJANGO_SETTINGS_MODULE altogether, relying on calling django.conf.settings.configure() and then invoking pytest. """ - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") - p = testdir.makepyfile(run=""" + p = testdir.makepyfile( + run=""" from django.conf import settings settings.configure(SECRET_KEY='set from settings.configure()', DATABASES={'default': { @@ -172,9 +194,11 @@ def test_django_settings_configure(testdir, monkeypatch): import pytest pytest.main() - """) + """ + ) - testdir.makepyfile(""" + testdir.makepyfile( + """ import pytest from django.conf import settings @@ -199,16 +223,16 @@ def test_user_count(self): def test_user_count(): assert User.objects.count() == 0 - """) + """ + ) result = testdir.runpython(p) - result.stdout.fnmatch_lines([ - "*4 passed*", - ]) + result.stdout.fnmatch_lines(["*4 passed*"]) def test_settings_in_hook(testdir, monkeypatch): - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') - testdir.makeconftest(""" + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") + testdir.makeconftest( + """ from django.conf import settings def pytest_configure(): @@ -218,8 +242,10 @@ def pytest_configure(): 'NAME': ':memory:'}}, INSTALLED_APPS=['django.contrib.auth', 'django.contrib.contenttypes',]) - """) - testdir.makepyfile(""" + """ + ) + testdir.makepyfile( + """ import pytest from django.conf import settings from django.contrib.auth.models import User @@ -230,7 +256,8 @@ def test_access_to_setting(): @pytest.mark.django_db def test_user_count(): assert User.objects.count() == 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 @@ -239,20 +266,23 @@ def test_django_not_loaded_without_settings(testdir, monkeypatch): """ Make sure Django is not imported at all if no Django settings is specified. """ - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') - testdir.makepyfile(""" + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") + testdir.makepyfile( + """ import sys def test_settings(): assert 'django' not in sys.modules - """) + """ + ) result = testdir.runpytest_subprocess() - result.stdout.fnmatch_lines(['*1 passed*']) + result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 def test_debug_false(testdir, monkeypatch): - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') - testdir.makeconftest(""" + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") + testdir.makeconftest( + """ from django.conf import settings def pytest_configure(): @@ -263,27 +293,35 @@ def pytest_configure(): 'NAME': ':memory:'}}, INSTALLED_APPS=['django.contrib.auth', 'django.contrib.contenttypes',]) - """) + """ + ) - testdir.makepyfile(""" + testdir.makepyfile( + """ from django.conf import settings def test_debug_is_false(): assert settings.DEBUG is False - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 -@pytest.mark.skipif(not hasattr(django, 'setup'), - reason="This Django version does not support app loading") -@pytest.mark.django_project(extra_settings=""" +@pytest.mark.skipif( + not hasattr(django, "setup"), + reason="This Django version does not support app loading", +) +@pytest.mark.django_project( + extra_settings=""" INSTALLED_APPS = [ 'tpkg.app.apps.TestApp', ] -""") +""" +) def test_django_setup_sequence(django_testdir): - django_testdir.create_app_file(""" + django_testdir.create_app_file( + """ from django.apps import apps, AppConfig @@ -296,9 +334,12 @@ def ready(self): except AttributeError: # Django < 2.0 populating = apps._lock.locked() print('READY(): populating=%r' % populating) - """, 'apps.py') + """, + "apps.py", + ) - django_testdir.create_app_file(""" + django_testdir.create_app_file( + """ from django.apps import apps try: @@ -308,10 +349,13 @@ def ready(self): print('IMPORT: populating=%r,ready=%r' % (populating, apps.ready)) SOME_THING = 1234 - """, 'models.py') + """, + "models.py", + ) - django_testdir.create_app_file("", '__init__.py') - django_testdir.makepyfile(""" + django_testdir.create_app_file("", "__init__.py") + django_testdir.makepyfile( + """ from django.apps import apps from tpkg.app.models import SOME_THING @@ -322,15 +366,16 @@ def test_anything(): populating = apps._lock.locked() print('TEST: populating=%r,ready=%r' % (populating, apps.ready)) - """) + """ + ) - result = django_testdir.runpytest_subprocess('-s', '--tb=line') - result.stdout.fnmatch_lines(['*IMPORT: populating=True,ready=False*']) - result.stdout.fnmatch_lines(['*READY(): populating=True*']) + result = django_testdir.runpytest_subprocess("-s", "--tb=line") + result.stdout.fnmatch_lines(["*IMPORT: populating=True,ready=False*"]) + result.stdout.fnmatch_lines(["*READY(): populating=True*"]) if django.VERSION < (2, 0): - result.stdout.fnmatch_lines(['*TEST: populating=False,ready=True*']) + result.stdout.fnmatch_lines(["*TEST: populating=False,ready=True*"]) else: - result.stdout.fnmatch_lines(['*TEST: populating=True,ready=True*']) + result.stdout.fnmatch_lines(["*TEST: populating=True,ready=True*"]) assert result.ret == 0 @@ -338,9 +383,10 @@ def test_no_ds_but_django_imported(testdir, monkeypatch): """pytest-django should not bail out, if "django" has been imported somewhere, e.g. via pytest-splinter.""" - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") - testdir.makepyfile(""" + testdir.makepyfile( + """ import os import django @@ -354,15 +400,16 @@ def test_env(): def test_cfg(pytestconfig): assert pytestconfig.option.ds is None - """) - r = testdir.runpytest_subprocess('-s') + """ + ) + r = testdir.runpytest_subprocess("-s") assert r.ret == 0 def test_no_django_settings_but_django_imported(testdir, monkeypatch): """Make sure we do not crash when Django happens to be imported, but settings is not properly configured""" - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') - testdir.makeconftest('import django') - r = testdir.runpytest_subprocess('--help') + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") + testdir.makeconftest("import django") + r = testdir.runpytest_subprocess("--help") assert r.ret == 0 diff --git a/tests/test_environment.py b/tests/test_environment.py index bf88e909c..510deffe1 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -18,24 +18,24 @@ # This is possible with some of the testdir magic, but this is the lazy way # to do it. -@pytest.mark.parametrize('subject', ['subject1', 'subject2']) + +@pytest.mark.parametrize("subject", ["subject1", "subject2"]) def test_autoclear_mailbox(subject): assert len(mail.outbox) == 0 - mail.send_mail(subject, 'body', 'from@example.com', ['to@example.com']) + mail.send_mail(subject, "body", "from@example.com", ["to@example.com"]) assert len(mail.outbox) == 1 m = mail.outbox[0] assert m.subject == subject - assert m.body == 'body' - assert m.from_email == 'from@example.com' - assert m.to == ['to@example.com'] + assert m.body == "body" + assert m.from_email == "from@example.com" + assert m.to == ["to@example.com"] class TestDirectAccessWorksForDjangoTestCase(TestCase): - def _do_test(self): assert len(mail.outbox) == 0 - mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com']) + mail.send_mail("subject", "body", "from@example.com", ["to@example.com"]) assert len(mail.outbox) == 1 def test_one(self): @@ -45,15 +45,18 @@ def test_two(self): self._do_test() -@pytest.mark.django_project(extra_settings=""" +@pytest.mark.django_project( + extra_settings=""" TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ) ROOT_URLCONF = 'tpkg.app.urls' - """) + """ +) def test_invalid_template_variable(django_testdir): - django_testdir.create_app_file(""" + django_testdir.create_app_file( + """ from django.conf.urls import url from pytest_django_test.compat import patterns @@ -63,23 +66,27 @@ def test_invalid_template_variable(django_testdir): '', url(r'invalid_template/', views.invalid_template), ) - """, 'urls.py') - django_testdir.create_app_file(""" + """, + "urls.py", + ) + django_testdir.create_app_file( + """ from django.shortcuts import render def invalid_template(request): return render(request, 'invalid_template.html', {}) - """, 'views.py') + """, + "views.py", + ) django_testdir.create_app_file( - "
{{ invalid_var }}
", - 'templates/invalid_template_base.html' + "
{{ invalid_var }}
", "templates/invalid_template_base.html" ) django_testdir.create_app_file( - "{% include 'invalid_template_base.html' %}", - 'templates/invalid_template.html' + "{% include 'invalid_template_base.html' %}", "templates/invalid_template.html" ) - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest def test_for_invalid_template(client): @@ -88,28 +95,36 @@ def test_for_invalid_template(client): @pytest.mark.ignore_template_errors def test_ignore(client): client.get('/invalid_template/') - ''') - result = django_testdir.runpytest_subprocess('-s', '--fail-on-template-vars') + """ + ) + result = django_testdir.runpytest_subprocess("-s", "--fail-on-template-vars") if get_django_version() >= (1, 9): origin = "'*/tpkg/app/templates/invalid_template_base.html'" else: origin = "'invalid_template.html'" - result.stdout.fnmatch_lines_random([ - "tpkg/test_the_test.py F.*", - "E * Failed: Undefined template variable 'invalid_var' in {}".format(origin) - ]) + result.stdout.fnmatch_lines_random( + [ + "tpkg/test_the_test.py F.*", + "E * Failed: Undefined template variable 'invalid_var' in {}".format( + origin + ), + ] + ) -@pytest.mark.django_project(extra_settings=""" +@pytest.mark.django_project( + extra_settings=""" TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ) ROOT_URLCONF = 'tpkg.app.urls' - """) + """ +) def test_invalid_template_variable_opt_in(django_testdir): - django_testdir.create_app_file(""" + django_testdir.create_app_file( + """ from django.conf.urls import url from pytest_django_test.compat import patterns @@ -119,19 +134,24 @@ def test_invalid_template_variable_opt_in(django_testdir): '', url(r'invalid_template/', views.invalid_template), ) - """, 'urls.py') - django_testdir.create_app_file(""" + """, + "urls.py", + ) + django_testdir.create_app_file( + """ from django.shortcuts import render def invalid_template(request): return render(request, 'invalid_template.html', {}) - """, 'views.py') + """, + "views.py", + ) django_testdir.create_app_file( - "
{{ invalid_var }}
", - 'templates/invalid_template.html' + "
{{ invalid_var }}
", "templates/invalid_template.html" ) - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest def test_for_invalid_template(client): @@ -140,17 +160,16 @@ def test_for_invalid_template(client): @pytest.mark.ignore_template_errors def test_ignore(client): client.get('/invalid_template/') - ''') - result = django_testdir.runpytest_subprocess('-s') - result.stdout.fnmatch_lines_random([ - "tpkg/test_the_test.py ..*", - ]) + """ + ) + result = django_testdir.runpytest_subprocess("-s") + result.stdout.fnmatch_lines_random(["tpkg/test_the_test.py ..*"]) @pytest.mark.django_db def test_database_rollback(): assert Item.objects.count() == 0 - Item.objects.create(name='blah') + Item.objects.create(name="blah") assert Item.objects.count() == 1 @@ -161,8 +180,8 @@ def test_database_rollback_again(): @pytest.mark.django_db def test_database_name(): - dirname, name = os.path.split(connection.settings_dict['NAME']) - assert 'file:memorydb' in name or name == ':memory:' or name.startswith('test_') + dirname, name = os.path.split(connection.settings_dict["NAME"]) + assert "file:memorydb" in name or name == ":memory:" or name.startswith("test_") def test_database_noaccess(): @@ -177,88 +196,98 @@ class TestrunnerVerbosity: @pytest.fixture def testdir(self, django_testdir): print("testdir") - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import pytest @pytest.mark.django_db def test_inner_testrunner(): pass - ''') + """ + ) return django_testdir def test_default(self, testdir): """Not verbose by default.""" - result = testdir.runpytest_subprocess('-s') - result.stdout.fnmatch_lines([ - "tpkg/test_the_test.py .*"]) + result = testdir.runpytest_subprocess("-s") + result.stdout.fnmatch_lines(["tpkg/test_the_test.py .*"]) def test_vq_verbosity_0(self, testdir): """-v and -q results in verbosity 0.""" - result = testdir.runpytest_subprocess('-s', '-v', '-q') - result.stdout.fnmatch_lines([ - "tpkg/test_the_test.py .*"]) + result = testdir.runpytest_subprocess("-s", "-v", "-q") + result.stdout.fnmatch_lines(["tpkg/test_the_test.py .*"]) def test_verbose_with_v(self, testdir): """Verbose output with '-v'.""" - result = testdir.runpytest_subprocess('-s', '-v') - result.stdout.fnmatch_lines_random([ - 'tpkg/test_the_test.py:*', - '*PASSED*', - ]) + result = testdir.runpytest_subprocess("-s", "-v") + result.stdout.fnmatch_lines_random(["tpkg/test_the_test.py:*", "*PASSED*"]) if get_django_version() >= (2, 2): - result.stderr.fnmatch_lines([ - "*Destroying test database for alias 'default'*"]) + result.stderr.fnmatch_lines( + ["*Destroying test database for alias 'default'*"] + ) else: - result.stdout.fnmatch_lines([ - "*Destroying test database for alias 'default'...*"]) + result.stdout.fnmatch_lines( + ["*Destroying test database for alias 'default'...*"] + ) def test_more_verbose_with_vv(self, testdir): """More verbose output with '-v -v'.""" - result = testdir.runpytest_subprocess('-s', '-v', '-v') - result.stdout.fnmatch_lines_random([ - 'tpkg/test_the_test.py:*', - '*Operations to perform:*', - '*Apply all migrations:*', - '*PASSED*']) + result = testdir.runpytest_subprocess("-s", "-v", "-v") + result.stdout.fnmatch_lines_random( + [ + "tpkg/test_the_test.py:*", + "*Operations to perform:*", + "*Apply all migrations:*", + "*PASSED*", + ] + ) if get_django_version() >= (2, 2): - result.stderr.fnmatch_lines([ - '*Creating test database for alias*', - "*Destroying test database for alias 'default'*"]) + result.stderr.fnmatch_lines( + [ + "*Creating test database for alias*", + "*Destroying test database for alias 'default'*", + ] + ) else: - result.stdout.fnmatch_lines([ - '*Creating test database for alias*', - "*Destroying test database for alias 'default'*"]) + result.stdout.fnmatch_lines( + [ + "*Creating test database for alias*", + "*Destroying test database for alias 'default'*", + ] + ) def test_more_verbose_with_vv_and_reusedb(self, testdir): """More verbose output with '-v -v', and --create-db.""" - result = testdir.runpytest_subprocess('-s', '-v', '-v', '--create-db') - result.stdout.fnmatch_lines([ - 'tpkg/test_the_test.py:*', - '*PASSED*']) + result = testdir.runpytest_subprocess("-s", "-v", "-v", "--create-db") + result.stdout.fnmatch_lines(["tpkg/test_the_test.py:*", "*PASSED*"]) if get_django_version() >= (2, 2): - result.stderr.fnmatch_lines(['*Creating test database for alias*']) - assert ("*Destroying test database for alias 'default' ('*')...*" - not in result.stderr.str()) + result.stderr.fnmatch_lines(["*Creating test database for alias*"]) + assert ( + "*Destroying test database for alias 'default' ('*')...*" + not in result.stderr.str() + ) else: - result.stdout.fnmatch_lines(['*Creating test database for alias*']) - assert ("*Destroying test database for alias 'default' ('*')...*" - not in result.stdout.str()) + result.stdout.fnmatch_lines(["*Creating test database for alias*"]) + assert ( + "*Destroying test database for alias 'default' ('*')...*" + not in result.stdout.str() + ) @pytest.mark.django_db -@pytest.mark.parametrize('site_name', ['site1', 'site2']) +@pytest.mark.parametrize("site_name", ["site1", "site2"]) def test_clear_site_cache(site_name, rf, monkeypatch): - request = rf.get('/') - monkeypatch.setattr(request, 'get_host', lambda: 'foo.com') - Site.objects.create(domain='foo.com', name=site_name) + request = rf.get("/") + monkeypatch.setattr(request, "get_host", lambda: "foo.com") + Site.objects.create(domain="foo.com", name=site_name) assert Site.objects.get_current(request=request).name == site_name @pytest.mark.django_db -@pytest.mark.parametrize('site_name', ['site1', 'site2']) +@pytest.mark.parametrize("site_name", ["site1", "site2"]) def test_clear_site_cache_check_site_cache_size(site_name, settings): assert len(site_models.SITE_CACHE) == 0 - site = Site.objects.create(domain='foo.com', name=site_name) + site = Site.objects.create(domain="foo.com", name=site_name) settings.SITE_ID = site.id assert Site.objects.get_current() == site assert len(site_models.SITE_CACHE) == 1 diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py index 891a64f8e..f5bd706bc 100644 --- a/tests/test_fixtures.py +++ b/tests/test_fixtures.py @@ -29,14 +29,14 @@ def test_client(client): @pytest.mark.django_db def test_admin_client(admin_client): assert isinstance(admin_client, Client) - resp = admin_client.get('/admin-required/') - assert force_text(resp.content) == 'You are an admin' + resp = admin_client.get("/admin-required/") + assert force_text(resp.content) == "You are an admin" def test_admin_client_no_db_marker(admin_client): assert isinstance(admin_client, Client) - resp = admin_client.get('/admin-required/') - assert force_text(resp.content) == 'You are an admin' + resp = admin_client.get("/admin-required/") + assert force_text(resp.content) == "You are an admin" @pytest.mark.django_db @@ -55,55 +55,59 @@ def test_rf(rf): @pytest.mark.django_db def test_django_assert_num_queries_db(django_assert_num_queries): with django_assert_num_queries(3): - Item.objects.create(name='foo') - Item.objects.create(name='bar') - Item.objects.create(name='baz') + Item.objects.create(name="foo") + Item.objects.create(name="bar") + Item.objects.create(name="baz") with pytest.raises(pytest.fail.Exception) as excinfo: with django_assert_num_queries(2) as captured: - Item.objects.create(name='quux') + Item.objects.create(name="quux") assert excinfo.value.args == ( - 'Expected to perform 2 queries but 1 was done ' - '(add -v option to show queries)',) + "Expected to perform 2 queries but 1 was done " + "(add -v option to show queries)", + ) assert len(captured.captured_queries) == 1 @pytest.mark.django_db def test_django_assert_max_num_queries_db(django_assert_max_num_queries): with django_assert_max_num_queries(2): - Item.objects.create(name='1-foo') - Item.objects.create(name='2-bar') + Item.objects.create(name="1-foo") + Item.objects.create(name="2-bar") with pytest.raises(pytest.fail.Exception) as excinfo: with django_assert_max_num_queries(2) as captured: - Item.objects.create(name='1-foo') - Item.objects.create(name='2-bar') - Item.objects.create(name='3-quux') + Item.objects.create(name="1-foo") + Item.objects.create(name="2-bar") + Item.objects.create(name="3-quux") assert excinfo.value.args == ( - 'Expected to perform 2 queries or less but 3 were done ' - '(add -v option to show queries)',) + "Expected to perform 2 queries or less but 3 were done " + "(add -v option to show queries)", + ) assert len(captured.captured_queries) == 3 - assert '1-foo' in captured.captured_queries[0]['sql'] + assert "1-foo" in captured.captured_queries[0]["sql"] @pytest.mark.django_db(transaction=True) def test_django_assert_num_queries_transactional_db( - transactional_db, django_assert_num_queries): + transactional_db, django_assert_num_queries +): with transaction.atomic(): with django_assert_num_queries(3): - Item.objects.create(name='foo') - Item.objects.create(name='bar') - Item.objects.create(name='baz') + Item.objects.create(name="foo") + Item.objects.create(name="bar") + Item.objects.create(name="baz") with pytest.raises(pytest.fail.Exception): with django_assert_num_queries(2): - Item.objects.create(name='quux') + Item.objects.create(name="quux") def test_django_assert_num_queries_output(django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ from django.contrib.contenttypes.models import ContentType import pytest @@ -112,14 +116,16 @@ def test_queries(django_assert_num_queries): with django_assert_num_queries(1): list(ContentType.objects.all()) ContentType.objects.count() - """) - result = django_testdir.runpytest_subprocess('--tb=short') - result.stdout.fnmatch_lines(['*Expected to perform 1 queries but 2 were done*']) + """ + ) + result = django_testdir.runpytest_subprocess("--tb=short") + result.stdout.fnmatch_lines(["*Expected to perform 1 queries but 2 were done*"]) assert result.ret == 1 def test_django_assert_num_queries_output_verbose(django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ from django.contrib.contenttypes.models import ContentType import pytest @@ -128,13 +134,12 @@ def test_queries(django_assert_num_queries): with django_assert_num_queries(11): list(ContentType.objects.all()) ContentType.objects.count() - """) - result = django_testdir.runpytest_subprocess('--tb=short', '-v') - result.stdout.fnmatch_lines([ - '*Expected to perform 11 queries but 2 were done*', - '*Queries:*', - '*========*', - ]) + """ + ) + result = django_testdir.runpytest_subprocess("--tb=short", "-v") + result.stdout.fnmatch_lines( + ["*Expected to perform 11 queries but 2 were done*", "*Queries:*", "*========*"] + ) assert result.ret == 1 @@ -143,10 +148,10 @@ def test_django_assert_num_queries_db_connection(django_assert_num_queries): from django.db import connection with django_assert_num_queries(1, connection=connection): - Item.objects.create(name='foo') + Item.objects.create(name="foo") with django_assert_num_queries(1, connection=None): - Item.objects.create(name='foo') + Item.objects.create(name="foo") with pytest.raises(AttributeError): with django_assert_num_queries(1, connection=False): @@ -157,37 +162,37 @@ class TestSettings: """Tests for the settings fixture, order matters""" def test_modify_existing(self, settings): - assert settings.SECRET_KEY == 'foobar' - assert real_settings.SECRET_KEY == 'foobar' - settings.SECRET_KEY = 'spam' - assert settings.SECRET_KEY == 'spam' - assert real_settings.SECRET_KEY == 'spam' + assert settings.SECRET_KEY == "foobar" + assert real_settings.SECRET_KEY == "foobar" + settings.SECRET_KEY = "spam" + assert settings.SECRET_KEY == "spam" + assert real_settings.SECRET_KEY == "spam" def test_modify_existing_again(self, settings): - assert settings.SECRET_KEY == 'foobar' - assert real_settings.SECRET_KEY == 'foobar' + assert settings.SECRET_KEY == "foobar" + assert real_settings.SECRET_KEY == "foobar" def test_new(self, settings): - assert not hasattr(settings, 'SPAM') - assert not hasattr(real_settings, 'SPAM') - settings.SPAM = 'ham' - assert settings.SPAM == 'ham' - assert real_settings.SPAM == 'ham' + assert not hasattr(settings, "SPAM") + assert not hasattr(real_settings, "SPAM") + settings.SPAM = "ham" + assert settings.SPAM == "ham" + assert real_settings.SPAM == "ham" def test_new_again(self, settings): - assert not hasattr(settings, 'SPAM') - assert not hasattr(real_settings, 'SPAM') + assert not hasattr(settings, "SPAM") + assert not hasattr(real_settings, "SPAM") def test_deleted(self, settings): - assert hasattr(settings, 'SECRET_KEY') - assert hasattr(real_settings, 'SECRET_KEY') + assert hasattr(settings, "SECRET_KEY") + assert hasattr(real_settings, "SECRET_KEY") del settings.SECRET_KEY - assert not hasattr(settings, 'SECRET_KEY') - assert not hasattr(real_settings, 'SECRET_KEY') + assert not hasattr(settings, "SECRET_KEY") + assert not hasattr(real_settings, "SECRET_KEY") def test_deleted_again(self, settings): - assert hasattr(settings, 'SECRET_KEY') - assert hasattr(real_settings, 'SECRET_KEY') + assert hasattr(settings, "SECRET_KEY") + assert hasattr(real_settings, "SECRET_KEY") def test_signals(self, settings): result = [] @@ -196,24 +201,24 @@ def assert_signal(signal, sender, setting, value, enter): result.append((setting, value, enter)) from django.test.signals import setting_changed + setting_changed.connect(assert_signal) result = [] - settings.SECRET_KEY = 'change 1' - settings.SECRET_KEY = 'change 2' + settings.SECRET_KEY = "change 1" + settings.SECRET_KEY = "change 2" assert result == [ - ('SECRET_KEY', 'change 1', True), - ('SECRET_KEY', 'change 2', True), + ("SECRET_KEY", "change 1", True), + ("SECRET_KEY", "change 2", True), ] result = [] - settings.FOOBAR = 'abc123' - assert sorted(result) == [ - ('FOOBAR', 'abc123', True), - ] + settings.FOOBAR = "abc123" + assert sorted(result) == [("FOOBAR", "abc123", True)] def test_modification_signal(self, django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ import pytest from django.conf import settings @@ -242,32 +247,40 @@ def test_set(settings): def test_set_non_existent(settings): settings.FOOBAR = 'abc123' - """) + """ + ) - result = django_testdir.runpytest_subprocess('--tb=short', '-v', '-s') + result = django_testdir.runpytest_subprocess("--tb=short", "-v", "-s") # test_set - result.stdout.fnmatch_lines([ - '*Setting changed: enter=True,setting=SECRET_KEY,value=change 1*', - '*Setting changed: enter=True,setting=SECRET_KEY,value=change 2*', - '*Setting changed: enter=False,setting=SECRET_KEY,value=change 1*', - '*Setting changed: enter=False,setting=SECRET_KEY,value=foobar*', - ]) + result.stdout.fnmatch_lines( + [ + "*Setting changed: enter=True,setting=SECRET_KEY,value=change 1*", + "*Setting changed: enter=True,setting=SECRET_KEY,value=change 2*", + "*Setting changed: enter=False,setting=SECRET_KEY,value=change 1*", + "*Setting changed: enter=False,setting=SECRET_KEY,value=foobar*", + ] + ) - result.stdout.fnmatch_lines([ - '*Setting changed: enter=True,setting=FOOBAR,value=abc123*', - ('*Setting changed: enter=False,setting=FOOBAR,value=None,' - 'actual_value=<>*'), - ]) + result.stdout.fnmatch_lines( + [ + "*Setting changed: enter=True,setting=FOOBAR,value=abc123*", + ( + "*Setting changed: enter=False,setting=FOOBAR,value=None," + "actual_value=<>*" + ), + ] + ) class TestLiveServer: def test_settings_before(self): from django.conf import settings - assert '%s.%s' % ( - settings.__class__.__module__, - settings.__class__.__name__) == 'django.conf.Settings' + assert ( + "%s.%s" % (settings.__class__.__module__, settings.__class__.__name__) + == "django.conf.Settings" + ) TestLiveServer._test_settings_before_run = True def test_url(self, live_server): @@ -282,63 +295,65 @@ def test_settings_restored(self): from django.conf import settings assert TestLiveServer._test_settings_before_run is True - assert '%s.%s' % ( - settings.__class__.__module__, - settings.__class__.__name__) == 'django.conf.Settings' + assert ( + "%s.%s" % (settings.__class__.__module__, settings.__class__.__name__) + == "django.conf.Settings" + ) if django.VERSION >= (1, 11): - assert settings.ALLOWED_HOSTS == ['testserver'] + assert settings.ALLOWED_HOSTS == ["testserver"] else: - assert settings.ALLOWED_HOSTS == ['*'] + assert settings.ALLOWED_HOSTS == ["*"] def test_transactions(self, live_server): if not connections_support_transactions(): - pytest.skip('transactions required for this test') + pytest.skip("transactions required for this test") assert not connection.in_atomic_block def test_db_changes_visibility(self, live_server): - response_data = urlopen(live_server + '/item_count/').read() - assert force_text(response_data) == 'Item count: 0' - Item.objects.create(name='foo') - response_data = urlopen(live_server + '/item_count/').read() - assert force_text(response_data) == 'Item count: 1' + response_data = urlopen(live_server + "/item_count/").read() + assert force_text(response_data) == "Item count: 0" + Item.objects.create(name="foo") + response_data = urlopen(live_server + "/item_count/").read() + assert force_text(response_data) == "Item count: 1" def test_fixture_db(self, db, live_server): - Item.objects.create(name='foo') - response_data = urlopen(live_server + '/item_count/').read() - assert force_text(response_data) == 'Item count: 1' + Item.objects.create(name="foo") + response_data = urlopen(live_server + "/item_count/").read() + assert force_text(response_data) == "Item count: 1" def test_fixture_transactional_db(self, transactional_db, live_server): - Item.objects.create(name='foo') - response_data = urlopen(live_server + '/item_count/').read() - assert force_text(response_data) == 'Item count: 1' + Item.objects.create(name="foo") + response_data = urlopen(live_server + "/item_count/").read() + assert force_text(response_data) == "Item count: 1" @pytest.fixture def item(self): # This has not requested database access explicitly, but the # live_server fixture auto-uses the transactional_db fixture. - Item.objects.create(name='foo') + Item.objects.create(name="foo") def test_item(self, item, live_server): pass @pytest.fixture def item_db(self, db): - return Item.objects.create(name='foo') + return Item.objects.create(name="foo") def test_item_db(self, item_db, live_server): - response_data = urlopen(live_server + '/item_count/').read() - assert force_text(response_data) == 'Item count: 1' + response_data = urlopen(live_server + "/item_count/").read() + assert force_text(response_data) == "Item count: 1" @pytest.fixture def item_transactional_db(self, transactional_db): - return Item.objects.create(name='foo') + return Item.objects.create(name="foo") def test_item_transactional_db(self, item_transactional_db, live_server): - response_data = urlopen(live_server + '/item_count/').read() - assert force_text(response_data) == 'Item count: 1' + response_data = urlopen(live_server + "/item_count/").read() + assert force_text(response_data) == "Item count: 1" - @pytest.mark.django_project(extra_settings=""" + @pytest.mark.django_project( + extra_settings=""" INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', @@ -349,13 +364,15 @@ def test_item_transactional_db(self, item_transactional_db, live_server): ] STATIC_URL = '/static/' - """) + """ + ) def test_serve_static_with_staticfiles_app(self, django_testdir, settings): """ LiveServer always serves statics with ``django.contrib.staticfiles`` handler. """ - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ import pytest from django.utils.encoding import force_text @@ -371,53 +388,63 @@ def test_a(self, live_server, settings): response_data = urlopen( live_server + '/static/a_file.txt').read() assert force_text(response_data) == 'bla\\n' - """) - result = django_testdir.runpytest_subprocess('--tb=short', '-v') - result.stdout.fnmatch_lines(['*test_a*PASSED*']) + """ + ) + result = django_testdir.runpytest_subprocess("--tb=short", "-v") + result.stdout.fnmatch_lines(["*test_a*PASSED*"]) assert result.ret == 0 - def test_serve_static_dj17_without_staticfiles_app(self, live_server, - settings): + def test_serve_static_dj17_without_staticfiles_app(self, live_server, settings): """ Because ``django.contrib.staticfiles`` is not installed LiveServer can not serve statics with django >= 1.7 . """ with pytest.raises(HTTPError): - urlopen(live_server + '/static/a_file.txt').read() + urlopen(live_server + "/static/a_file.txt").read() - @pytest.mark.skipif(get_django_version() < (1, 11), - reason='Django >= 1.11 required') + @pytest.mark.skipif( + get_django_version() < (1, 11), reason="Django >= 1.11 required" + ) def test_specified_port_range_error_message_django_111(self, django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ def test_with_live_server(live_server): pass - """) + """ + ) - result = django_testdir.runpytest_subprocess('--liveserver=localhost:1234-2345') - result.stdout.fnmatch_lines([ - '*Specifying multiple live server ports is not supported in Django 1.11. This ' - 'will be an error in a future pytest-django release.*' - ]) + result = django_testdir.runpytest_subprocess("--liveserver=localhost:1234-2345") + result.stdout.fnmatch_lines( + [ + "*Specifying multiple live server ports is not supported in Django 1.11. This " + "will be an error in a future pytest-django release.*" + ] + ) - @pytest.mark.skipif(get_django_version() < (1, 11, 2), - reason='Django >= 1.11.2 required') + @pytest.mark.skipif( + get_django_version() < (1, 11, 2), reason="Django >= 1.11.2 required" + ) def test_specified_port_django_111(self, django_testdir): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: - sock.bind(('', 0)) + sock.bind(("", 0)) __, port = sock.getsockname() finally: sock.close() - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ def test_with_live_server(live_server): assert live_server.port == %d - """ % port) + """ + % port + ) - django_testdir.runpytest_subprocess('--liveserver=localhost:%s' % port) + django_testdir.runpytest_subprocess("--liveserver=localhost:%s" % port) -@pytest.mark.django_project(extra_settings=""" +@pytest.mark.django_project( + extra_settings=""" AUTH_USER_MODEL = 'app.MyCustomUser' INSTALLED_APPS = [ 'django.contrib.auth', @@ -427,9 +454,11 @@ def test_with_live_server(live_server): 'tpkg.app', ] ROOT_URLCONF = 'tpkg.app.urls' - """) + """ +) def test_custom_user_model(django_testdir): - django_testdir.create_app_file(""" + django_testdir.create_app_file( + """ from django.contrib.auth.models import AbstractUser from django.db import models @@ -437,8 +466,11 @@ class MyCustomUser(AbstractUser): identifier = models.CharField(unique=True, max_length=100) USERNAME_FIELD = 'identifier' - """, 'models.py') - django_testdir.create_app_file(""" + """, + "models.py", + ) + django_testdir.create_app_file( + """ from django.conf.urls import url from pytest_django_test.compat import patterns from tpkg.app import views @@ -447,8 +479,11 @@ class MyCustomUser(AbstractUser): '', url(r'admin-required/', views.admin_required_view), ) - """, 'urls.py') - django_testdir.create_app_file(""" + """, + "urls.py", + ) + django_testdir.create_app_file( + """ from django.http import HttpResponse from django.template import Template from django.template.context import Context @@ -460,18 +495,23 @@ def admin_required_view(request): Template('You are an admin').render(Context())) return HttpResponse( Template('Access denied').render(Context())) - """, 'views.py') - django_testdir.makepyfile(""" + """, + "views.py", + ) + django_testdir.makepyfile( + """ from django.utils.encoding import force_text from tpkg.app.models import MyCustomUser def test_custom_user_model(admin_client): resp = admin_client.get('/admin-required/') assert force_text(resp.content) == 'You are an admin' - """) + """ + ) - django_testdir.create_app_file('', 'migrations/__init__.py') - django_testdir.create_app_file(""" + django_testdir.create_app_file("", "migrations/__init__.py") + django_testdir.create_app_file( + """ # -*- coding: utf-8 -*- from __future__ import unicode_literals @@ -514,10 +554,12 @@ class Migration(migrations.Migration): bases=None, ), ] - """, 'migrations/0002_custom_user_model.py') # noqa + """, + "migrations/0002_custom_user_model.py", + ) # noqa - result = django_testdir.runpytest_subprocess('-s') - result.stdout.fnmatch_lines(['*1 passed*']) + result = django_testdir.runpytest_subprocess("-s") + result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 @@ -550,15 +592,17 @@ def test_unblock_with_block(self, django_db_blocker): def test_mail(mailoutbox): - assert mailoutbox is mail.outbox # check that mail.outbox and fixture value is same object + assert ( + mailoutbox is mail.outbox + ) # check that mail.outbox and fixture value is same object assert len(mailoutbox) == 0 - mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com']) + mail.send_mail("subject", "body", "from@example.com", ["to@example.com"]) assert len(mailoutbox) == 1 m = mailoutbox[0] - assert m.subject == 'subject' - assert m.body == 'body' - assert m.from_email == 'from@example.com' - assert list(m.to) == ['to@example.com'] + assert m.subject == "subject" + assert m.body == "body" + assert m.from_email == "from@example.com" + assert list(m.to) == ["to@example.com"] def test_mail_again(mailoutbox): @@ -566,14 +610,15 @@ def test_mail_again(mailoutbox): def test_mail_message_uses_mocked_DNS_NAME(mailoutbox): - mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com']) + mail.send_mail("subject", "body", "from@example.com", ["to@example.com"]) m = mailoutbox[0] message = m.message() - assert message['Message-ID'].endswith('@fake-tests.example.com>') + assert message["Message-ID"].endswith("@fake-tests.example.com>") def test_mail_message_uses_django_mail_dnsname_fixture(django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ from django.core import mail import pytest @@ -587,14 +632,16 @@ def test_mailbox_inner(mailoutbox): m = mailoutbox[0] message = m.message() assert message['Message-ID'].endswith('@from.django_mail_dnsname>') - """) - result = django_testdir.runpytest_subprocess('--tb=short', '-v') - result.stdout.fnmatch_lines(['*test_mailbox_inner*PASSED*']) + """ + ) + result = django_testdir.runpytest_subprocess("--tb=short", "-v") + result.stdout.fnmatch_lines(["*test_mailbox_inner*PASSED*"]) assert result.ret == 0 def test_mail_message_dns_patching_can_be_skipped(django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ from django.core import mail import pytest @@ -618,10 +665,10 @@ def mocked_make_msgid(*args, **kwargs): assert len(mocked_make_msgid.called) == 1 assert mocked_make_msgid.called[0][1]['domain'] is mail.DNS_NAME - """) - result = django_testdir.runpytest_subprocess('--tb=short', '-vv', '-s') - result.stdout.fnmatch_lines([ - '*test_mailbox_inner*', - 'django_mail_dnsname_mark', - 'PASSED*']) + """ + ) + result = django_testdir.runpytest_subprocess("--tb=short", "-vv", "-s") + result.stdout.fnmatch_lines( + ["*test_mailbox_inner*", "django_mail_dnsname_mark", "PASSED*"] + ) assert result.ret == 0 diff --git a/tests/test_initialization.py b/tests/test_initialization.py index 51cfac5f1..47680e942 100644 --- a/tests/test_initialization.py +++ b/tests/test_initialization.py @@ -6,7 +6,8 @@ def test_django_setup_order_and_uniqueness(django_testdir, monkeypatch): The django.setup() function shall not be called multiple times by pytest-django, since it resets logging conf each time. """ - django_testdir.makeconftest(''' + django_testdir.makeconftest( + """ import django.apps assert django.apps.apps.ready from tpkg.app.models import Item @@ -16,9 +17,12 @@ def pytest_configure(): import django print("pytest_configure: conftest") django.setup = lambda: SHOULD_NOT_GET_CALLED - ''') + """ + ) - django_testdir.project_root.join('tpkg', 'plugin.py').write(dedent(''' + django_testdir.project_root.join("tpkg", "plugin.py").write( + dedent( + """ import pytest import django.apps assert not django.apps.apps.ready @@ -33,18 +37,24 @@ def pytest_configure(): def pytest_load_initial_conftests(early_config, parser, args): print("pytest_load_initial_conftests") assert not django.apps.apps.ready - ''')) - django_testdir.makepyfile(""" + """ + ) + ) + django_testdir.makepyfile( + """ def test_ds(): pass - """) - result = django_testdir.runpytest_subprocess('-s', '-p', 'tpkg.plugin') - result.stdout.fnmatch_lines([ - 'plugin', - 'pytest_load_initial_conftests', - 'conftest', - 'pytest_configure: conftest', - 'pytest_configure: plugin', - '*1 passed*', - ]) + """ + ) + result = django_testdir.runpytest_subprocess("-s", "-p", "tpkg.plugin") + result.stdout.fnmatch_lines( + [ + "plugin", + "pytest_load_initial_conftests", + "conftest", + "pytest_configure: conftest", + "pytest_configure: plugin", + "*1 passed*", + ] + ) assert result.ret == 0 diff --git a/tests/test_manage_py_scan.py b/tests/test_manage_py_scan.py index c650104d7..5639c46ea 100644 --- a/tests/test_manage_py_scan.py +++ b/tests/test_manage_py_scan.py @@ -1,8 +1,7 @@ import pytest -@pytest.mark.django_project(project_root='django_project_root', - create_manage_py=True) +@pytest.mark.django_project(project_root="django_project_root", create_manage_py=True) def test_django_project_found(django_testdir): # XXX: Important: Do not chdir() to django_project_root since runpytest_subprocess # will call "python /path/to/pytest.py", which will impliclity add cwd to @@ -11,87 +10,95 @@ def test_django_project_found(django_testdir): # This matches the behaviour when pytest is called directly as an # executable (cwd is not added to the Python path) - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ def test_foobar(): assert 1 + 1 == 2 - """) + """ + ) - result = django_testdir.runpytest_subprocess('django_project_root') + result = django_testdir.runpytest_subprocess("django_project_root") assert result.ret == 0 outcomes = result.parseoutcomes() - assert outcomes['passed'] == 1 + assert outcomes["passed"] == 1 -@pytest.mark.django_project(project_root='django_project_root', - create_manage_py=True) +@pytest.mark.django_project(project_root="django_project_root", create_manage_py=True) def test_django_project_found_absolute(django_testdir, monkeypatch): """This only tests that "." is added as an absolute path (#637).""" - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ def test_dot_not_in_syspath(): import sys assert '.' not in sys.path[:5] - """) - monkeypatch.chdir('django_project_root') + """ + ) + monkeypatch.chdir("django_project_root") # NOTE: the "." here is important to test for an absolute path being used. - result = django_testdir.runpytest_subprocess('-s', '.') + result = django_testdir.runpytest_subprocess("-s", ".") assert result.ret == 0 outcomes = result.parseoutcomes() - assert outcomes['passed'] == 1 + assert outcomes["passed"] == 1 -@pytest.mark.django_project(project_root='django_project_root', - create_manage_py=True) +@pytest.mark.django_project(project_root="django_project_root", create_manage_py=True) def test_django_project_found_invalid_settings(django_testdir, monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DOES_NOT_EXIST') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "DOES_NOT_EXIST") - result = django_testdir.runpytest_subprocess('django_project_root') + result = django_testdir.runpytest_subprocess("django_project_root") assert result.ret != 0 - result.stderr.fnmatch_lines(['*ImportError:*DOES_NOT_EXIST*']) - result.stderr.fnmatch_lines(['*pytest-django found a Django project*']) + result.stderr.fnmatch_lines(["*ImportError:*DOES_NOT_EXIST*"]) + result.stderr.fnmatch_lines(["*pytest-django found a Django project*"]) -def test_django_project_scan_disabled_invalid_settings(django_testdir, - monkeypatch): - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DOES_NOT_EXIST') +def test_django_project_scan_disabled_invalid_settings(django_testdir, monkeypatch): + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "DOES_NOT_EXIST") - django_testdir.makeini(''' + django_testdir.makeini( + """ [pytest] django_find_project = false - ''') + """ + ) - result = django_testdir.runpytest_subprocess('django_project_root') + result = django_testdir.runpytest_subprocess("django_project_root") assert result.ret != 0 - result.stderr.fnmatch_lines(['*ImportError*DOES_NOT_EXIST*']) - result.stderr.fnmatch_lines(['*pytest-django did not search for ' - 'Django projects*']) + result.stderr.fnmatch_lines(["*ImportError*DOES_NOT_EXIST*"]) + result.stderr.fnmatch_lines( + ["*pytest-django did not search for " "Django projects*"] + ) -@pytest.mark.django_project(project_root='django_project_root', - create_manage_py=True) +@pytest.mark.django_project(project_root="django_project_root", create_manage_py=True) def test_django_project_found_invalid_settings_version(django_testdir, monkeypatch): """Invalid DSM should not cause an error with --help or --version.""" - monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DOES_NOT_EXIST') + monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "DOES_NOT_EXIST") - result = django_testdir.runpytest_subprocess('django_project_root', '--version') + result = django_testdir.runpytest_subprocess("django_project_root", "--version") assert result.ret == 0 - result.stderr.fnmatch_lines(['*This is pytest version*']) + result.stderr.fnmatch_lines(["*This is pytest version*"]) - result = django_testdir.runpytest_subprocess('django_project_root', '--help') + result = django_testdir.runpytest_subprocess("django_project_root", "--help") assert result.ret == 0 - result.stdout.fnmatch_lines(['*usage:*']) + result.stdout.fnmatch_lines(["*usage:*"]) -@pytest.mark.django_project(project_root='django_project_root', - create_manage_py=True) +@pytest.mark.django_project(project_root="django_project_root", create_manage_py=True) def test_runs_without_error_on_long_args(django_testdir): - django_testdir.create_test_module(""" + django_testdir.create_test_module( + """ def test_this_is_a_long_message_which_caused_a_bug_when_scanning_for_manage_py_12346712341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234112341234112451234123412341234123412341234123412341234123412341234123412341234123412341234123412341234(): assert 1 + 1 == 2 - """) - - result = django_testdir.runpytest_subprocess('-k', 'this_is_a_long_message_which_caused_a_bug_when_scanning_for_manage_py_12346712341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234112341234112451234123412341234123412341234123412341234123412341234123412341234123412341234123412341234', 'django_project_root') + """ + ) + + result = django_testdir.runpytest_subprocess( + "-k", + "this_is_a_long_message_which_caused_a_bug_when_scanning_for_manage_py_12346712341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234112341234112451234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", + "django_project_root", + ) assert result.ret == 0 diff --git a/tests/test_unittest.py b/tests/test_unittest.py index 3d89a39c4..7f9efd97d 100644 --- a/tests/test_unittest.py +++ b/tests/test_unittest.py @@ -5,11 +5,11 @@ class TestFixtures(TestCase): - fixtures = ['items'] + fixtures = ["items"] def test_fixtures(self): assert Item.objects.count() == 1 - assert Item.objects.get().name == 'Fixture item' + assert Item.objects.get().name == "Fixture item" def test_fixtures_again(self): """Ensure fixtures are only loaded once.""" @@ -20,13 +20,13 @@ class TestSetup(TestCase): def setUp(self): """setUp should be called after starting a transaction""" assert Item.objects.count() == 0 - Item.objects.create(name='Some item') - Item.objects.create(name='Some item again') + Item.objects.create(name="Some item") + Item.objects.create(name="Some item again") def test_count(self): self.assertEqual(Item.objects.count(), 2) assert Item.objects.count() == 2 - Item.objects.create(name='Foo') + Item.objects.create(name="Foo") self.assertEqual(Item.objects.count(), 3) def test_count_again(self): @@ -38,15 +38,15 @@ def tearDown(self): class TestFixturesWithSetup(TestCase): - fixtures = ['items'] + fixtures = ["items"] def setUp(self): assert Item.objects.count() == 1 - Item.objects.create(name='Some item') + Item.objects.create(name="Some item") def test_count(self): assert Item.objects.count() == 2 - Item.objects.create(name='Some item again') + Item.objects.create(name="Some item again") def test_count_again(self): self.test_count() @@ -61,7 +61,8 @@ def test_sole_test(django_testdir): are collected, without the django_db marker. """ - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ import os from django.test import TestCase @@ -78,19 +79,20 @@ def test_foo(self): # Make sure it is usable assert Item.objects.count() == 0 - ''') + """ + ) - result = django_testdir.runpytest_subprocess('-v') - result.stdout.fnmatch_lines([ - "*TestFoo*test_foo PASSED*", - ]) + result = django_testdir.runpytest_subprocess("-v") + result.stdout.fnmatch_lines(["*TestFoo*test_foo PASSED*"]) assert result.ret == 0 class TestUnittestMethods: "Test that setup/teardown methods of unittests are being called." + def test_django(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import TestCase class TestFoo(TestCase): @@ -110,20 +112,24 @@ def tearDownClass(self): def test_pass(self): pass - ''') - - result = django_testdir.runpytest_subprocess('-v', '-s') - result.stdout.fnmatch_lines([ - "CALLED: setUpClass", - "CALLED: setUp", - "CALLED: tearDown", - "PASSED*", - "CALLED: tearDownClass", - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v", "-s") + result.stdout.fnmatch_lines( + [ + "CALLED: setUpClass", + "CALLED: setUp", + "CALLED: tearDown", + "PASSED*", + "CALLED: tearDownClass", + ] + ) assert result.ret == 0 def test_setUpClass_not_being_a_classmethod(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import TestCase class TestFoo(TestCase): @@ -132,17 +138,21 @@ def setUpClass(self): def test_pass(self): pass - ''') - - result = django_testdir.runpytest_subprocess('-v', '-s') - result.stdout.fnmatch_lines([ - "* ERROR at setup of TestFoo.test_pass *", - "E *Failed: .setUpClass should be a classmethod", # noqa:E501 - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v", "-s") + result.stdout.fnmatch_lines( + [ + "* ERROR at setup of TestFoo.test_pass *", + "E *Failed: .setUpClass should be a classmethod", # noqa:E501 + ] + ) assert result.ret == 1 def test_setUpClass_multiple_subclasses(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import TestCase @@ -163,20 +173,24 @@ def test_bar1(self): class TestBar2(TestFoo): def test_bar21(self): pass - ''') - - result = django_testdir.runpytest_subprocess('-v') - result.stdout.fnmatch_lines([ - "*TestFoo::test_shared PASSED*", - "*TestBar::test_bar1 PASSED*", - "*TestBar::test_shared PASSED*", - "*TestBar2::test_bar21 PASSED*", - "*TestBar2::test_shared PASSED*", - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v") + result.stdout.fnmatch_lines( + [ + "*TestFoo::test_shared PASSED*", + "*TestBar::test_bar1 PASSED*", + "*TestBar::test_shared PASSED*", + "*TestBar2::test_bar21 PASSED*", + "*TestBar2::test_shared PASSED*", + ] + ) assert result.ret == 0 def test_setUpClass_mixin(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import TestCase class TheMixin(object): @@ -193,17 +207,18 @@ def test_foo(self): class TestBar(TheMixin, TestCase): def test_bar(self): pass - ''') + """ + ) - result = django_testdir.runpytest_subprocess('-v') - result.stdout.fnmatch_lines([ - "*TestFoo::test_foo PASSED*", - "*TestBar::test_bar PASSED*", - ]) + result = django_testdir.runpytest_subprocess("-v") + result.stdout.fnmatch_lines( + ["*TestFoo::test_foo PASSED*", "*TestBar::test_bar PASSED*"] + ) assert result.ret == 0 def test_setUpClass_skip(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import TestCase import pytest @@ -227,20 +242,24 @@ def test_bar1(self): class TestBar2(TestFoo): def test_bar21(self): pass - ''') - - result = django_testdir.runpytest_subprocess('-v') - result.stdout.fnmatch_lines([ - "*TestFoo::test_shared SKIPPED*", - "*TestBar::test_bar1 PASSED*", - "*TestBar::test_shared PASSED*", - "*TestBar2::test_bar21 PASSED*", - "*TestBar2::test_shared PASSED*", - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v") + result.stdout.fnmatch_lines( + [ + "*TestFoo::test_shared SKIPPED*", + "*TestBar::test_bar1 PASSED*", + "*TestBar::test_shared PASSED*", + "*TestBar2::test_bar21 PASSED*", + "*TestBar2::test_shared PASSED*", + ] + ) assert result.ret == 0 def test_multi_inheritance_setUpClass(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import TestCase from .app.models import Item @@ -298,14 +317,16 @@ def tearDownClass(cls): def test_c(self): assert self.state == self.expected_state - ''') + """ + ) - result = django_testdir.runpytest_subprocess('-vvvv', '-s') - assert result.parseoutcomes()['passed'] == 6 + result = django_testdir.runpytest_subprocess("-vvvv", "-s") + assert result.parseoutcomes()["passed"] == 6 assert result.ret == 0 def test_unittest(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from unittest import TestCase class TestFoo(TestCase): @@ -325,20 +346,24 @@ def tearDownClass(self): def test_pass(self): pass - ''') - - result = django_testdir.runpytest_subprocess('-v', '-s') - result.stdout.fnmatch_lines([ - "CALLED: setUpClass", - "CALLED: setUp", - "CALLED: tearDown", - "PASSED*", - "CALLED: tearDownClass", - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-v", "-s") + result.stdout.fnmatch_lines( + [ + "CALLED: setUpClass", + "CALLED: setUp", + "CALLED: tearDown", + "PASSED*", + "CALLED: tearDownClass", + ] + ) assert result.ret == 0 def test_setUpClass_leaf_but_not_in_dunder_dict(self, django_testdir): - django_testdir.create_test_module(''' + django_testdir.create_test_module( + """ from django.test import testcases class CMSTestCase(testcases.TestCase): @@ -355,19 +380,18 @@ class TestContact(CMSTestCase, FooBarTestCase): def test_noop(self): print('test_noop') - ''') - - result = django_testdir.runpytest_subprocess('-q', '-s') - result.stdout.fnmatch_lines([ - "*FooBarTestCase.setUpClass*", - "*test_noop*", - "1 passed*", - ]) + """ + ) + + result = django_testdir.runpytest_subprocess("-q", "-s") + result.stdout.fnmatch_lines( + ["*FooBarTestCase.setUpClass*", "*test_noop*", "1 passed*"] + ) assert result.ret == 0 class TestCaseWithDbFixture(TestCase): - pytestmark = pytest.mark.usefixtures('db') + pytestmark = pytest.mark.usefixtures("db") def test_simple(self): # We only want to check setup/teardown does not conflict @@ -375,7 +399,7 @@ def test_simple(self): class TestCaseWithTrDbFixture(TestCase): - pytestmark = pytest.mark.usefixtures('transactional_db') + pytestmark = pytest.mark.usefixtures("transactional_db") def test_simple(self): # We only want to check setup/teardown does not conflict @@ -391,7 +415,8 @@ def test_pdb_enabled(django_testdir): https://github.com/pytest-dev/pytest-django/issues/405 """ - django_testdir.create_test_module(''' + django_testdir.create_test_module( + ''' import os from django.test import TestCase @@ -419,7 +444,8 @@ def tearDown(self): """tearDown should be called before rolling back the database""" assert Item.objects.count() == 3 - ''') + ''' + ) - result = django_testdir.runpytest_subprocess('-v', '--pdb') + result = django_testdir.runpytest_subprocess("-v", "--pdb") assert result.ret == 0 diff --git a/tests/test_urls.py b/tests/test_urls.py index dd45c8f13..f50996118 100644 --- a/tests/test_urls.py +++ b/tests/test_urls.py @@ -3,24 +3,25 @@ from django.utils.encoding import force_text -@pytest.mark.urls('pytest_django_test.urls_overridden') +@pytest.mark.urls("pytest_django_test.urls_overridden") def test_urls(): try: from django.urls import is_valid_path except ImportError: from django.core.urlresolvers import is_valid_path - assert settings.ROOT_URLCONF == 'pytest_django_test.urls_overridden' - assert is_valid_path('/overridden_url/') + assert settings.ROOT_URLCONF == "pytest_django_test.urls_overridden" + assert is_valid_path("/overridden_url/") -@pytest.mark.urls('pytest_django_test.urls_overridden') +@pytest.mark.urls("pytest_django_test.urls_overridden") def test_urls_client(client): - response = client.get('/overridden_url/') - assert force_text(response.content) == 'Overridden urlconf works!' + response = client.get("/overridden_url/") + assert force_text(response.content) == "Overridden urlconf works!" def test_urls_cache_is_cleared(testdir): - testdir.makepyfile(myurls=""" + testdir.makepyfile( + myurls=""" from django.conf.urls import url from pytest_django_test.compat import patterns @@ -28,9 +29,11 @@ def fake_view(request): pass urlpatterns = patterns('', url(r'first/$', fake_view, name='first')) - """) + """ + ) - testdir.makepyfile(""" + testdir.makepyfile( + """ try: from django.urls import reverse, NoReverseMatch except ImportError: # Django < 2.0 @@ -46,14 +49,16 @@ def test_something_else(): with pytest.raises(NoReverseMatch): reverse('first') - """) + """ + ) result = testdir.runpytest_subprocess() assert result.ret == 0 def test_urls_cache_is_cleared_and_new_urls_can_be_assigned(testdir): - testdir.makepyfile(myurls=""" + testdir.makepyfile( + myurls=""" from django.conf.urls import url from pytest_django_test.compat import patterns @@ -61,9 +66,11 @@ def fake_view(request): pass urlpatterns = patterns('', url(r'first/$', fake_view, name='first')) - """) + """ + ) - testdir.makepyfile(myurls2=""" + testdir.makepyfile( + myurls2=""" from django.conf.urls import url from pytest_django_test.compat import patterns @@ -71,9 +78,11 @@ def fake_view(request): pass urlpatterns = patterns('', url(r'second/$', fake_view, name='second')) - """) + """ + ) - testdir.makepyfile(""" + testdir.makepyfile( + """ try: from django.urls import reverse, NoReverseMatch except ImportError: # Django < 2.0 @@ -90,7 +99,8 @@ def test_something_else(): reverse('first') reverse('second') - """) + """ + ) result = testdir.runpytest_subprocess() assert result.ret == 0 diff --git a/tests/test_without_django_loaded.py b/tests/test_without_django_loaded.py index 2fe455734..eb6409947 100644 --- a/tests/test_without_django_loaded.py +++ b/tests/test_without_django_loaded.py @@ -4,14 +4,15 @@ @pytest.fixture def no_ds(monkeypatch): """Ensure DJANGO_SETTINGS_MODULE is unset""" - monkeypatch.delenv('DJANGO_SETTINGS_MODULE') + monkeypatch.delenv("DJANGO_SETTINGS_MODULE") -pytestmark = pytest.mark.usefixtures('no_ds') +pytestmark = pytest.mark.usefixtures("no_ds") def test_no_ds(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ import os def test_env(): @@ -19,13 +20,15 @@ def test_env(): def test_cfg(pytestconfig): assert pytestconfig.option.ds is None - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 def test_database(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ import pytest @pytest.mark.django_db @@ -41,63 +44,74 @@ def test_db(db): def test_transactional_db(transactional_db): assert 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 - r.stdout.fnmatch_lines(['*4 skipped*']) + r.stdout.fnmatch_lines(["*4 skipped*"]) def test_client(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_client(client): assert 0 def test_admin_client(admin_client): assert 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 - r.stdout.fnmatch_lines(['*2 skipped*']) + r.stdout.fnmatch_lines(["*2 skipped*"]) def test_rf(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_rf(rf): assert 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 - r.stdout.fnmatch_lines(['*1 skipped*']) + r.stdout.fnmatch_lines(["*1 skipped*"]) def test_settings(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_settings(settings): assert 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 - r.stdout.fnmatch_lines(['*1 skipped*']) + r.stdout.fnmatch_lines(["*1 skipped*"]) def test_live_server(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_live_server(live_server): assert 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 - r.stdout.fnmatch_lines(['*1 skipped*']) + r.stdout.fnmatch_lines(["*1 skipped*"]) def test_urls_mark(testdir): - testdir.makepyfile(""" + testdir.makepyfile( + """ import pytest @pytest.mark.urls('foo.bar') def test_urls(): assert 0 - """) + """ + ) r = testdir.runpytest_subprocess() assert r.ret == 0 - r.stdout.fnmatch_lines(['*1 skipped*']) + r.stdout.fnmatch_lines(["*1 skipped*"])