pytest-dev / pytest-dev/pytest-django
Django app for custom user model and django_db fixture: during test setup of db migrations: error when run on Linux but Windows is OK.
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 367
- PR merge metrics
- No merged PRs in 30d
Description
I am setting up my testing environment and my first pytest-django test works on Windows but errors out on Linux.
I'm using a django custom user model as recommended for new projects:
https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
For pytest-django, I specify django_db:
pytestmark = [ pytest.mark.django_db ]
so I can do db testing.
On both Windows and Linux platforms, I've done the django migration for my custom user model.
dj_user_app
[X] 0001_initial
When I run on Windows:
>pytest -vs all_tests/django_tests/django_test.py::Test_django_operations::test_auth_a_non_user
===================================================================== test session starts =====================================================================
platform win32 -- Python 3.9.2, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- h:\business\projects\...\scripts\python.exe
cachedir: .pytest_cache
django: settings: www_dj_project.mysite.settings (from ini)
rootdir: H:\business\projects\..._1, configfile: pytest.ini
plugins: django-4.4.0, pythonpath-0.7.3
collected 1 item
all_tests/django_tests/django_test.py::Test_django_operations::test_auth_a_non_user Creating test database for alias 'default'...
Creating test database for alias 'reg_test_queen_bee_engine'...
Creating test database for alias 'reg_test_worker_bee_engine'...
PASSEDDestroying test database for alias 'default'...
Destroying test database for alias 'reg_test_queen_bee_engine'...
Destroying test database for alias 'reg_test_worker_bee_engine'...
====================================================================== 1 passed in 4.07s ======================================================================
When I run on Linux:
$ pytest -vs all_tests/django_tests/django_test.py::Test_django_operations::test_auth_a_non_user
====================================================================== test session starts =======================================================================
platform linux -- Python 3.8.10, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /home/.../bin/python3
cachedir: .pytest_cache
django: settings: www_dj_project.mysite.settings (from ini)
rootdir: /home/..._1, configfile: pytest.ini
plugins: django-4.4.0, pythonpath-0.7.3
collected 1 item
all_tests/django_tests/django_test.py::Test_django_operations::test_auth_a_non_user Creating test database for alias 'default'...
ERROR
============================================================================= ERRORS =============================================================================
_________________________________________________ ERROR at setup of Test_django_operations.test_auth_a_non_user __________________________________________________
self = <django.db.migrations.loader.MigrationLoader object at 0x7f7e715f5ee0>, key = ('dj_user_app', '__first__'), current_app = 'admin'
def check_key(self, key, current_app):
if (key[1] != "__first__" and key[1] != "__latest__") or key in self.graph:
return key
# Special-case __first__, which means "the first migration" for
# migrated apps, and is ignored for unmigrated apps. It allows
# makemigrations to declare dependencies on apps before they even have
# migrations.
if key[0] == current_app:
# Ignore __first__ references to the same app (#22325)
return
if key[0] in self.unmigrated_apps:
# This app isn't migrated, but something depends on it.
# The models will get auto-added into the state, though
# so we're fine.
return
if key[0] in self.migrated_apps:
try:
if key[1] == "__first__":
> return self.graph.root_nodes(key[0])[0]
E IndexError: list index out of range
../../../../webapps/.../lib/python3.8/site-packages/django/db/migrations/loader.py:174: IndexError
During handling of the above exception, another exception occurred:
request = <SubRequest '_django_db_marker' for <Function test_auth_a_non_user>>
@pytest.fixture(autouse=True)
def _django_db_marker(request) -> None:
"""Implement the django_db marker, internal to pytest-django.
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")
if marker:
transaction, reset_sequences, databases = validate_django_db(marker)
# TODO: Use pytest Store (item.store) once that's stable.
request.node._pytest_django_databases = databases
if reset_sequences:
request.getfixturevalue("django_db_reset_sequences")
elif transaction:
request.getfixturevalue("transactional_db")
else:
> request.getfixturevalue("db")
../../../../webapps/.../lib/python3.8/site-packages/pytest_django/plugin.py:470:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../webapps/.../lib/python3.8/site-packages/pytest_django/fixtures.py:117: in django_db_setup
db_cfg = setup_databases(
../../../../webapps/.../lib/python3.8/site-packages/django/test/utils.py:179: in setup_databases
connection.creation.create_test_db(
../../../../webapps/.../lib/python3.8/site-packages/django/db/backends/base/creation.py:74: in create_test_db
call_command(
../../../../webapps/.../lib/python3.8/site-packages/django/core/management/__init__.py:181: in call_command
return command.execute(*args, **defaults)
../../../../webapps/.../lib/python3.8/site-packages/django/core/management/base.py:398: in execute
output = self.handle(*args, **options)
../../../../webapps/.../lib/python3.8/site-packages/django/core/management/base.py:89: in wrapped
res = handle_func(*args, **kwargs)
../../../../webapps/.../lib/python3.8/site-packages/django/core/management/commands/migrate.py:92: in handle
executor = MigrationExecutor(connection, self.migration_progress_callback)
../../../../webapps/.../lib/python3.8/site-packages/django/db/migrations/executor.py:18: in __init__
self.loader = MigrationLoader(self.connection)
../../../../webapps/.../lib/python3.8/site-packages/django/db/migrations/loader.py:53: in __init__
self.build_graph()
../../../../webapps/.../lib/python3.8/site-packages/django/db/migrations/loader.py:235: in build_graph
self.add_external_dependencies(key, migration)
../../../../webapps/.../lib/python3.8/site-packages/django/db/migrations/loader.py:199: in add_external_dependencies
parent = self.check_key(parent, key[0])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.migrations.loader.MigrationLoader object at 0x7f7e715f5ee0>, key = ('dj_user_app', '__first__'), current_app = 'admin'
def check_key(self, key, current_app):
if (key[1] != "__first__" and key[1] != "__latest__") or key in self.graph:
return key
# Special-case __first__, which means "the first migration" for
# migrated apps, and is ignored for unmigrated apps. It allows
# makemigrations to declare dependencies on apps before they even have
# migrations.
if key[0] == current_app:
# Ignore __first__ references to the same app (#22325)
return
if key[0] in self.unmigrated_apps:
# This app isn't migrated, but something depends on it.
# The models will get auto-added into the state, though
# so we're fine.
return
if key[0] in self.migrated_apps:
try:
if key[1] == "__first__":
return self.graph.root_nodes(key[0])[0]
else: # "__latest__"
return self.graph.leaf_nodes(key[0])[0]
except IndexError:
if self.ignore_no_migrations:
return None
else:
> raise ValueError("Dependency on app with no migrations: %s" % key[0])
E ValueError: Dependency on app with no migrations: dj_user_app
../../../../webapps/.../lib/python3.8/site-packages/django/db/migrations/loader.py:181: ValueError
==================================================================== short test summary info =====================================================================
ERROR all_tests/django_tests/django_test.py::Test_django_operations::test_auth_a_non_user - ValueError: Dependency on app with no migrations: dj_user_app
======================================================================== 1 error in 0.61s ========================================================================
Since the same code and db state works on Windows but errors out on Linux, I'm thinking it's a bug and maybe relating to django custom user models because the Linux error out is in db migration of the user model in the django admin app.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with all_tests/django_tests/django_test.py::Test_django_operations::test_auth_a_non_user and reproduce the Linux setup failure. Trace pytest_django/plugin.py and fixtures.py into Django's django/db/migrations/loader.py, comparing the migration state for dj_user_app on Windows and Linux. Done means the cause of the platform difference is identified and the test database setup succeeds consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- database, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100