【问题标题】:"Apps aren't loaded yet" when trying to run pytest-django尝试运行 pytest-django 时“尚未加载应用程序”
【发布时间】:2018-01-05 02:19:35
【问题描述】:

Django tutorial 中的(部分)投票应用为例,我试图让pytest-django 运行。

使用命令django-admin startproject mysite2,我创建了一个具有以下结构的项目目录:

.
├── db.sqlite3
├── manage.py
├── mysite2
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── pytest.ini

我的pytest.ini 看起来像

[pytest]
DJANGO_SETTINGS_MODULE = mysite2.settings
python_files = tests.py test_*.py *_tests.py

按照教程,我在polls/models.py 中创建了QuestionChoice 模型:

import datetime

from django.db import models
from django.utils import timezone

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

现在,如果我按照教程中的描述制作 tests.py,它基于 Python 的内置 unittest 模块,

import datetime

from django.utils import timezone
from django.test import TestCase

from .models import Question

class QuestionModelTests(TestCase):
    def test_was_published_recently_with_future_question(self):
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)

我从命令行运行python manage.py test,预期测试失败:

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/kurtpeek/Documents/Scratch/mysite2/polls/tests.py", line 23, in test_was_published_recently_with_future_question
    self.assertIs(future_question.was_published_recently(), False)
AssertionError: True is not False

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)
Destroying test database for alias 'default'...

但是,如果我将测试代码更改为(尝试的)pytest 等效项(即,不必继承 TestCase 并使用普通断言):

def test_was_published_recently_with_future_question():
    time = timezone.now() + datetime.timedelta(days=30)
    future_question = Question(pub_date=time)
    assert future_question.was_published_recently() is False

并运行pytest 命令,我得到以下错误:

================================= test session starts ==================================
platform darwin -- Python 3.6.3, pytest-3.2.3, py-1.4.34, pluggy-0.4.0
rootdir: /Users/kurtpeek/Documents/Scratch/mysite2, inifile: pytest.ini
plugins: timeout-1.2.1
collected 0 items / 1 errors                                                            

======================================== ERRORS ========================================
___________________________ ERROR collecting polls/tests.py ____________________________
polls/tests.py:10: in <module>
    from .models import Question
polls/models.py:6: in <module>
    class Question(models.Model):
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py:100: in __new__
    app_config = apps.get_containing_app_config(module)
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/apps/registry.py:244: in get_containing_app_config
    self.check_apps_ready()
/Library/Frameworks/Python.framework/Versions/3.6/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.64 seconds ================================

到目前为止,我还没有找到解决此问题的方法。关于如何让测试运行的任何想法?

【问题讨论】:

    标签: python django pytest pytest-django


    【解决方案1】:

    开箱即用,pytest 不知道 Django 数据库,即使安装了pytest-django。不过不要害怕:pytest-django 使您的测试可以轻松地使用其django_db pytest mark 访问 Django 数据库。

    试试这个:

    import pytest
    
    
    @pytest.mark.django_db
    def test_was_published_recently_with_future_question():
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        assert future_question.was_published_recently() is False
    

    【讨论】:

    • 我有类似的问题。对于偶然发现相同错误的人:pip uninstall django-pytestpip install pytest-django
    • 这对我有用。令人困惑的是如何也有 django-pytest!
    【解决方案2】:

    我在使用 pytestpython setup.py test 调用测试时遇到了类似的问题。

    对于pytest 调用,在我的虚拟环境中安装pytest-django 解决了这个问题。

    对于python setup.py installpytest-django 添加到setup()tests_require 参数解决了它。

    这是setup.py的sn-p:

    TEST_REQUIREMENTS = [
        'pytest',
        'pytest-django',
        'pylint',
        'pylint_django',
        'git-pylint-commit-hook',
    ]
    
    setup(
        name='foo',
        version='0.0.1',
        description='Foo package',
        author='...',
        author_email='...',
        packages=['foo'],
        install_requires=INSTALL_REQUIREMENTS,
        setup_requires=SETUP_REQUIREMENTS,
        tests_require=TEST_REQUIREMENTS,
    )
    

    【讨论】:

    • 这应该是接受的答案恕我直言。 pytest-django 是解决问题的粘合剂,让 Django 和 pytest 成为朋友。
    【解决方案3】:

    根据Django: AppRegistryNotReady(),当不使用manage.py 时,必须显式调用django.setup()。我通过从manage.py shell 运行pytest 测试验证了这一点:

    Kurts-MacBook-Pro:mysite2 kurtpeek$ python3 manage.py shell
    Python 3.6.3 (v3.6.3:2c5fed86e0, Oct  3 2017, 00:32:08) 
    Type 'copyright', 'credits' or 'license' for more information
    IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: import pytest
    
    In [2]: pytest.main('polls/tests.py')
    ================================= test session starts ==================================
    platform darwin -- Python 3.6.3, pytest-3.2.3, py-1.4.34, pluggy-0.4.0
    rootdir: /Users/kurtpeek/Documents/Scratch/mysite2, inifile: pytest.ini
    plugins: timeout-1.2.1
    collected 1 item                                                                        
    
    polls/tests.py F
    
    ======================================= FAILURES =======================================
    ___________________ test_was_published_recently_with_future_question ___________________
    
        def test_was_published_recently_with_future_question():
            time = timezone.now() + datetime.timedelta(days=30)
            future_question = Question(pub_date=time)
    >       assert future_question.was_published_recently() is False
    E    assert True is False
    E     +  where True = <bound method Question.was_published_recently of <Question: >>()
    E     +    where <bound method Question.was_published_recently of <Question: >> = <Question: >.was_published_recently
    
    polls/tests.py:18: AssertionError
    =================================== warnings summary ===================================
    None
      passing a string to pytest.main() is deprecated, pass a list of arguments instead.
    
    -- Docs: http://doc.pytest.org/en/latest/warnings.html
    ========================= 1 failed, 1 warnings in 0.14 seconds =========================
    Out[2]: 1
    

    然而,这并不是一个真正可接受的解决方案,因为测试需要可从命令行运行。是否有其他 pytest 装饰器来确保所需的设置?

    【讨论】:

      【解决方案4】:

      对我来说,将 DJANGO_SETTINGS_MODULE 设置为命令行或 pytest.ini 中的导出解决了这个问题。 似乎忽略了 conftest.py 中该环境变量的导出 如果我弄明白了,我会更新这篇文章。

      【讨论】:

        【解决方案5】:

        它是否在文档中的某处说测试应该在没有子类化django.test.TestCase 的情况下工作?我不认为django-pytest 在加载 django 应用方面有什么特别之处。因此,如果您的类继续从 TestCase 继承,您应该能够使用 pytest 的所有其他内容,例如它的断言、固定装置等。

        【讨论】:

        • 有趣的想法,但根据docs,“样板文件更少:无需导入单元测试,创建带有方法的子类。只需将测试编写为常规函数即可。”应该是pytest-django的优点之一,所以子类化应该是没有必要的。
        【解决方案6】:

        除了现有的pytest 之外,只需安装pytest-django,我的错误也消失了:D

        【讨论】:

          【解决方案7】:

          对我来说,问题是我忘记添加 pytest.ini 以将 pytest 链接到我的项目设置 - 请参阅 docs

          # -- FILE: pytest.ini (or tox.ini)
          [pytest]
          DJANGO_SETTINGS_MODULE = test.settings
          # -- recommended but optional:
          python_files = tests.py test_*.py *_tests.py
          

          【讨论】:

            猜你喜欢
            • 2018-11-29
            • 2017-08-21
            • 2020-05-02
            • 2019-05-10
            • 2016-08-04
            • 2016-06-01
            • 2016-01-08
            • 2016-08-06
            • 1970-01-01
            相关资源
            最近更新 更多