pytest-django icon indicating copy to clipboard operation
pytest-django copied to clipboard

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.

Open taigit opened this issue 3 years ago • 0 comments
trafficstars

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.

taigit avatar Nov 28 '21 17:11 taigit