"Apps aren't loaded yet" 尝试 运行 pytest-django
"Apps aren't loaded yet" when trying to run pytest-django
使用从 Django tutorial as an example, I'm trying to get 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
中创建了 Question
和 Choice
模型:
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 ================================
到目前为止我还没有找到解决这个问题的方法。关于如何让测试达到 运行 的任何想法?
开箱即用,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
根据 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
装饰器来确保所需的设置?
它是否在文档中的某个地方说测试应该在没有 subclassing django.test.TestCase
的情况下工作?我不认为 django-pytest
在加载 Django 应用程序方面有什么特别之处。因此,如果您的 class 继续继承自 TestCase
,您应该能够使用 pytest
的所有其他内容,例如它的断言、固定装置等
我在使用 pytest
或 python setup.py test
调用测试时遇到了类似的问题。
对于 pytest
调用,在我的虚拟环境中安装 pytest-django
解决了问题。
对于 python setup.py install
添加 pytest-django
到 setup()
的 tests_require
参数解决了它。
这是 setup.py
的片段:
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.ini 中将 DJANGO_SETTINGS_MODULE 设置为导出解决了问题。
它似乎忽略了 conftest.py 中那个环境变量的导出
如果我弄明白了,我会更新这个 post.
除了现有的 pytest
之外,只需安装 pytest-django
,我的错误也消失了 :D
对我来说,问题是我忘记将 pytest.ini
添加到 link 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
使用从 Django tutorial as an example, I'm trying to get 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
中创建了 Question
和 Choice
模型:
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 ================================
到目前为止我还没有找到解决这个问题的方法。关于如何让测试达到 运行 的任何想法?
开箱即用,pytest
不知道 Django 数据库,即使安装了 pytest-django
。不过,不要害怕:pytest-django
使您的测试可以使用其 django_db pytest mark.
试一试:
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
根据 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
装饰器来确保所需的设置?
它是否在文档中的某个地方说测试应该在没有 subclassing django.test.TestCase
的情况下工作?我不认为 django-pytest
在加载 Django 应用程序方面有什么特别之处。因此,如果您的 class 继续继承自 TestCase
,您应该能够使用 pytest
的所有其他内容,例如它的断言、固定装置等
我在使用 pytest
或 python setup.py test
调用测试时遇到了类似的问题。
对于 pytest
调用,在我的虚拟环境中安装 pytest-django
解决了问题。
对于 python setup.py install
添加 pytest-django
到 setup()
的 tests_require
参数解决了它。
这是 setup.py
的片段:
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.ini 中将 DJANGO_SETTINGS_MODULE 设置为导出解决了问题。 它似乎忽略了 conftest.py 中那个环境变量的导出 如果我弄明白了,我会更新这个 post.
除了现有的 pytest
之外,只需安装 pytest-django
,我的错误也消失了 :D
对我来说,问题是我忘记将 pytest.ini
添加到 link 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