django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet with Django pytest

3.5k Views Asked by At

I'm writing test for my Django 2.0 application.

I am using mixer and the directory structure is like

project
|- src
   |- contacts
      |- migrations
      |- tests
         |- __init__.py
         |- test_models.py
      |- __init__.py
      |- models.py
      |- apps.py
   |- koober                  <----   (main app)
      |- settings
         |- __init__.py
         |- local.py
         |- production.py
      |- __init__.py
      |- test_settings.py
      |- urls.py
      |- wsgi.py
   |- .coveragerc
   |- manage.py
   |- pytest.ini
|- other_files
|- not_related_to_project
|- Pipfile
|- Pipfile.lock
|- Procfile

When I run from project directory

project$ pipenv run py.test

It gives error as

============================================================================= test session starts ==============================================================================
platform linux -- Python 3.6.5, pytest-3.6.1, py-1.5.3, pluggy-0.6.0
rootdir: /home/anuj/code/python/koober, inifile:
plugins: django-3.3.0, cov-2.5.1
collected 0 items / 1 errors                                                                                                                                                   

==================================================================================== ERRORS ====================================================================================
______________________________________________________________ ERROR collecting src/contacts/tests/test_models.py ______________________________________________________________
src/contacts/tests/test_models.py:2: in <module>
    from mixer.backend.django import mixer
../../../.local/share/virtualenvs/koober-MOd9u5HA/lib/python3.6/site-packages/mixer/backend/django.py:11: in <module>
    from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation   # noqa
../../../.local/share/virtualenvs/koober-MOd9u5HA/lib/python3.6/site-packages/django/contrib/contenttypes/fields.py:3: in <module>
    from django.contrib.contenttypes.models import ContentType
../../../.local/share/virtualenvs/koober-MOd9u5HA/lib/python3.6/site-packages/django/contrib/contenttypes/models.py:134: in <module>
    class ContentType(models.Model):
../../../.local/share/virtualenvs/koober-MOd9u5HA/lib/python3.6/site-packages/django/db/models/base.py:100: in __new__
    app_config = apps.get_containing_app_config(module)
../../../.local/share/virtualenvs/koober-MOd9u5HA/lib/python3.6/site-packages/django/apps/registry.py:244: in get_containing_app_config
    self.check_apps_ready()
../../../.local/share/virtualenvs/koober-MOd9u5HA/lib/python3.6/site-packages/django/apps/registry.py:127: in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
E   django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
=========================================================================== 1 error in 0.31 seconds ============================================================================

When I run the same command from project/src file, it gives error as

ImportError: No module named 'koober.test_settings.py'; 'koober.test_settings' is not a package

I checked for any error with

project$ pipenv run python src/manage.py check

and it gives

System check identified no issues (0 silenced).

even pipenv run python src/manage.py runserver is working fine.

content of test_settings.py

from koober.settings import *

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:",
    }
}

EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

Updated test_settings.py

import os

import django

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "koober.settings")
django.setup()

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:",
    }
}

EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

contents of pytest.ini

[pytest]

DJANGO_SETTINGS_MODULE = koober.test_settings.py
addopts = --nomigrations --cov=. --cov-report=html

contents of src/contacts/tests/test_models.py

import pytest
from mixer.backend.django import mixer

from django.contrib.auth.models import User

pytestmark = pytest.mark.django_db


class TestContact:
    def test_model(self):
        user = mixer.blend(User)

Also, can see in pytest log, pytest.ini file is not detected when running pytest or py.test and inifile: is empty

Edit 3: What works for me

updated test_settings.py

from .settings import *

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:",
    }
}

EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

command running from /src directory

pipenv run pytest --ds=koober.test_settings
3

There are 3 best solutions below

1
On

I am not sure but it might seem that your test is not importing the django application along with its settings properly. Best way to emulate that is to include(import) whatever is there in manage.py,( whether you need to incude get wsgi application is a different debate) before your script. I have no experience with mixer but error looks like the django application is not being loaded in proper sequence.

Refer to this for the syntax. Importantly give correct path here

os.environ.setdefault("DJANGO_SETTINGS_MODULE", correctpath)

Also give the correct settings path i.e. make sure settings have all the neccesary stuff like installed apps and all other stuff like db conf to make it work and even if it doesnt have so u can import the missing ones from the working settings file like your local or production ones.

0
On

Where is your INSTALLED_APPS problem misconfiguration of this attribute, or you not at your app label at your app.py in your apps

0
On

In my case, after upgrading to Django 1.11, this started mysteriously happening. The solution was to use pytest's --ds parameter to tell pytest where to find our django settings. So our command went from:

pytest path/to/some/test.py

To:

pytest --ds proj.settings path/to/some/test.py

Weird, but fine, now it works.