如何为django可重用应用程序启动测试?

如何为django可重用应用程序启动测试?,django,testing,django-testing,Django,Testing,Django Testing,我可以为我的可重用Django应用程序启动测试,而不将此应用程序合并到项目中吗 我的应用程序使用了一些型号,因此有必要提供(测试)数据库*设置。我应该将它们存储在哪里以及如何启动测试 对于Django项目,我可以使用manage.py test运行测试;当我对我的独立应用程序使用django-admin.py测试时,我得到: 错误:无法导入设置, 因为环境变量 DJANGO_设置_模块未定义 这里的最佳实践是什么?对于我的可重用应用程序(),我使用buildout。我创建了example\u项目

我可以为我的可重用Django应用程序启动测试,而不将此应用程序合并到项目中吗

我的应用程序使用了一些型号,因此有必要提供
(测试)数据库*
设置。我应该将它们存储在哪里以及如何启动测试

对于Django项目,我可以使用
manage.py test
运行测试;当我对我的独立应用程序使用
django-admin.py测试时,我得到:

错误:无法导入设置, 因为环境变量 DJANGO_设置_模块未定义

这里的最佳实践是什么?

对于我的可重用应用程序(),我使用buildout。我创建了
example\u项目
,将其与buildout一起使用,对其运行测试。我只需将我的应用程序放在
示例项目的设置中

当我想安装项目使用的所有依赖项并运行测试时,我只需要执行以下操作:

  • 运行:python bootstrap.py
  • 运行构建:

    垃圾箱/建筑

  • 为Django 1.1和Django 1.2运行测试:

    箱子/试验-1.1 垃圾箱/测试-1.2

在这里,您可以找到如何配置可重用应用程序以使用buildout进行部署和运行测试的教程:

在这里,您可以找到我在项目中使用的构建配置示例:


我以这样的解决方案结束(它的灵感来自于django投票中的解决方案):

在测试目录中创建文件,例如“runtests.py”,其中包含:

import os, sys
from django.conf import settings

DIRNAME = os.path.dirname(__file__)
settings.configure(DEBUG = True,
                   DATABASE_ENGINE = 'sqlite3',
                   DATABASE_NAME = os.path.join(DIRNAME, 'database.db'),
                   INSTALLED_APPS = ('django.contrib.auth',
                                     'django.contrib.contenttypes',
                                     'django.contrib.sessions',
                                     'django.contrib.admin',
                                     'myapp',
                                     'myapp.tests',))


from django.test.simple import run_tests

failures = run_tests(['myapp',], verbosity=1)
if failures:
    sys.exit(failures)
它允许通过
python runtests.py
命令运行测试。
它不需要安装依赖项(例如构建),并且在将应用程序合并到更大的项目中时不会损害测试运行。

Django(>=1.4)测试运行程序的正确用法如下所示:

import django, sys
from django.conf import settings

settings.configure(DEBUG=True,
               DATABASES={
                    'default': {
                        'ENGINE': 'django.db.backends.sqlite3',
                    }
                },
               ROOT_URLCONF='myapp.urls',
               INSTALLED_APPS=('django.contrib.auth',
                              'django.contrib.contenttypes',
                              'django.contrib.sessions',
                              'django.contrib.admin',
                              'myapp',))

try:
    # Django < 1.8
    from django.test.simple import DjangoTestSuiteRunner
    test_runner = DjangoTestSuiteRunner(verbosity=1)
except ImportError:
    # Django >= 1.8
    django.setup()
    from django.test.runner import DiscoverRunner
    test_runner = DiscoverRunner(verbosity=1)

failures = test_runner.run_tests(['myapp'])
if failures:
    sys.exit(failures)
导入django,sys 从django.conf导入设置 configure(DEBUG=True, 数据库={ “默认值”:{ “引擎”:“django.db.backends.sqlite3”, } }, ROOT_URLCONF='myapp.url', 已安装的应用程序=('django.contrib.auth', “django.contrib.contenttypes”, “django.contrib.sessions”, “django.contrib.admin”, ‘我的应用’,)) 尝试: #Django<1.8 从django.test.simple导入DjangoTestSuiteRunner 测试运行程序=DjangoTestSuiteRunner(详细程度=1) 除恐怖外: #Django>=1.8 django.setup() 从django.test.runner导入DiscoveryRunner 测试运行程序=发现运行程序(详细程度=1) 失败=测试运行程序。运行测试(['myapp']) 如果出现故障: 系统退出(故障)
DjangoTestSuiteRunner和DiscoveryRunner具有大部分兼容的接口

有关更多信息,请参阅“定义测试运行程序”文档:

  • (Django>=1.4,=1.8)

对于Django 1.7,它略有不同。假设你有以下几点 应用程序的目录结构
foo

foo
|── docs
|── foo
│   ├── __init__.py
│   ├── models.py
│   ├── urls.py
│   └── views.py
└── tests
    ├── foo_models
    │   ├── __init__.py
    │   ├── ...
    │   └── tests.py
    ├── foo_views 
    │   ├── __init__.py
    │   ├── ...
    │   └── tests.py
    ├── runtests.py
    └── urls.py
这就是Django项目本身构造其测试的方式

您希望使用以下命令运行
foo/tests/
中的所有测试:

python3 runtests.py
您还希望能够从
tests
的父目录运行该命令,例如通过Tox或Invoke,就像
python3foo/tests/runtests.py

我在这里介绍的解决方案是可重用的,只需调整应用程序的名称
foo
(如果需要,还可以调整其他应用程序)。无法通过安装,因为它将错过数据库设置

需要以下文件:

url.py

"""
This urlconf exists because Django expects ROOT_URLCONF to exist. URLs
should be added within the test folders, and use TestCase.urls to set them.
This helps the tests remain isolated.
"""

urlpatterns = []
#!/usr/bin/env python3
import glob
import os
import sys

import django
from django.conf import settings
from django.core.management import execute_from_command_line


BASE_DIR = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.abspath(os.path.join(BASE_DIR, '..')))

# Unfortunately, apps can not be installed via ``modify_settings``
# decorator, because it would miss the database setup.
CUSTOM_INSTALLED_APPS = (
    'foo',
    'django.contrib.admin',
)

ALWAYS_INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

ALWAYS_MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)


settings.configure(
    SECRET_KEY="django_tests_secret_key",
    DEBUG=False,
    TEMPLATE_DEBUG=False,
    ALLOWED_HOSTS=[],
    INSTALLED_APPS=ALWAYS_INSTALLED_APPS + CUSTOM_INSTALLED_APPS,
    MIDDLEWARE_CLASSES=ALWAYS_MIDDLEWARE_CLASSES,
    ROOT_URLCONF='tests.urls',
    DATABASES={
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
        }
    },
    LANGUAGE_CODE='en-us',
    TIME_ZONE='UTC',
    USE_I18N=True,
    USE_L10N=True,
    USE_TZ=True,
    STATIC_URL='/static/',
    # Use a fast hasher to speed up tests.
    PASSWORD_HASHERS=(
        'django.contrib.auth.hashers.MD5PasswordHasher',
    ),
    FIXTURE_DIRS=glob.glob(BASE_DIR + '/' + '*/fixtures/')

)

django.setup()
args = [sys.argv[0], 'test']
# Current module (``tests``) and its submodules.
test_cases = '.'

# Allow accessing test options from the command line.
offset = 1
try:
    sys.argv[1]
except IndexError:
    pass
else:
    option = sys.argv[1].startswith('-')
    if not option:
        test_cases = sys.argv[1]
        offset = 2

args.append(test_cases)
# ``verbosity`` can be overwritten from command line.
args.append('--verbosity=2')
args.extend(sys.argv[offset:])

execute_from_command_line(args)
runtests.py

"""
This urlconf exists because Django expects ROOT_URLCONF to exist. URLs
should be added within the test folders, and use TestCase.urls to set them.
This helps the tests remain isolated.
"""

urlpatterns = []
#!/usr/bin/env python3
import glob
import os
import sys

import django
from django.conf import settings
from django.core.management import execute_from_command_line


BASE_DIR = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.abspath(os.path.join(BASE_DIR, '..')))

# Unfortunately, apps can not be installed via ``modify_settings``
# decorator, because it would miss the database setup.
CUSTOM_INSTALLED_APPS = (
    'foo',
    'django.contrib.admin',
)

ALWAYS_INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

ALWAYS_MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)


settings.configure(
    SECRET_KEY="django_tests_secret_key",
    DEBUG=False,
    TEMPLATE_DEBUG=False,
    ALLOWED_HOSTS=[],
    INSTALLED_APPS=ALWAYS_INSTALLED_APPS + CUSTOM_INSTALLED_APPS,
    MIDDLEWARE_CLASSES=ALWAYS_MIDDLEWARE_CLASSES,
    ROOT_URLCONF='tests.urls',
    DATABASES={
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
        }
    },
    LANGUAGE_CODE='en-us',
    TIME_ZONE='UTC',
    USE_I18N=True,
    USE_L10N=True,
    USE_TZ=True,
    STATIC_URL='/static/',
    # Use a fast hasher to speed up tests.
    PASSWORD_HASHERS=(
        'django.contrib.auth.hashers.MD5PasswordHasher',
    ),
    FIXTURE_DIRS=glob.glob(BASE_DIR + '/' + '*/fixtures/')

)

django.setup()
args = [sys.argv[0], 'test']
# Current module (``tests``) and its submodules.
test_cases = '.'

# Allow accessing test options from the command line.
offset = 1
try:
    sys.argv[1]
except IndexError:
    pass
else:
    option = sys.argv[1].startswith('-')
    if not option:
        test_cases = sys.argv[1]
        offset = 2

args.append(test_cases)
# ``verbosity`` can be overwritten from command line.
args.append('--verbosity=2')
args.extend(sys.argv[offset:])

execute_from_command_line(args)
一些设置是可选的;它们可以提高速度或改善更真实的环境


第二个参数指向当前目录。它在纯粹的pytest环境中使用了

,为了提供足够的Django环境,以便在没有实际Django项目的情况下为我的可重用应用程序运行测试,我需要以下几点:

pytest.ini:

[pytest]
DJANGO_SETTINGS_MODULE = test_settings
python_files = tests.py test_*.py *_tests.py
# You may need more or less than what's shown here - this is a skeleton:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
    }
}

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.messages',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.staticfiles',
    'todo',
)

ROOT_URLCONF = 'base_urls'

TEMPLATES = [
    {
        'DIRS': ['path/to/your/templates'), ],
    }
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
"""
This urlconf exists so we can run tests without an actual
Django project (Django expects ROOT_URLCONF to exist.)
It is not used by installed instances of this app.
"""

from django.urls import include, path

urlpatterns = [
    path('foo/', include('myapp.urls')),
]
测试设置。py:

[pytest]
DJANGO_SETTINGS_MODULE = test_settings
python_files = tests.py test_*.py *_tests.py
# You may need more or less than what's shown here - this is a skeleton:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
    }
}

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.messages',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.staticfiles',
    'todo',
)

ROOT_URLCONF = 'base_urls'

TEMPLATES = [
    {
        'DIRS': ['path/to/your/templates'), ],
    }
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
"""
This urlconf exists so we can run tests without an actual
Django project (Django expects ROOT_URLCONF to exist.)
It is not used by installed instances of this app.
"""

from django.urls import include, path

urlpatterns = [
    path('foo/', include('myapp.urls')),
]
base\u url.py:

[pytest]
DJANGO_SETTINGS_MODULE = test_settings
python_files = tests.py test_*.py *_tests.py
# You may need more or less than what's shown here - this is a skeleton:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
    }
}

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.messages',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.staticfiles',
    'todo',
)

ROOT_URLCONF = 'base_urls'

TEMPLATES = [
    {
        'DIRS': ['path/to/your/templates'), ],
    }
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
"""
This urlconf exists so we can run tests without an actual
Django project (Django expects ROOT_URLCONF to exist.)
It is not used by installed instances of this app.
"""

from django.urls import include, path

urlpatterns = [
    path('foo/', include('myapp.urls')),
]
模板/base.html:

[pytest]
DJANGO_SETTINGS_MODULE = test_settings
python_files = tests.py test_*.py *_tests.py
# You may need more or less than what's shown here - this is a skeleton:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
    }
}

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.messages',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.staticfiles',
    'todo',
)

ROOT_URLCONF = 'base_urls'

TEMPLATES = [
    {
        'DIRS': ['path/to/your/templates'), ],
    }
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
"""
This urlconf exists so we can run tests without an actual
Django project (Django expects ROOT_URLCONF to exist.)
It is not used by installed instances of this app.
"""

from django.urls import include, path

urlpatterns = [
    path('foo/', include('myapp.urls')),
]
如果您的任何测试命中实际视图,您的应用程序的模板可能会扩展项目
base.html
,因此该文件必须存在。在我的例子中,我刚刚创建了一个空文件
templates/base.html


我现在可以从我的独立可重用应用程序目录运行
pytest-x-v
,而无需Django项目。

我知道这是一个旧线程,但我发现,如果您的可重用应用程序有一个文件“tests.py”,那么您可以在项目文件夹中创建一个tests.py,然后编写以下内容

from reusableapp.tests import *

当您调用“python manage.py test”时,Django将运行这些测试。

Django不需要项目。你在问什么?您是否运行了
django-admin.py测试
?您观察到了什么?对于django项目,我通过:manage.py test运行测试,当我使用django-admin.py时,我得到:Error:无法导入设置,因为环境变量django_Settings_MODULE未定义。我相信这必须是非常简单的,但我与这个结巴。感谢有用的信息。看看这是否解决了我的问题(乍一看似乎有很多麻烦),但在其他方面可能会很有趣。答案很好!我在
/tests/
中添加了一个
\uuuu init\uuuuuuuuuuuuuuuuuuuuuuupy
,使其正常工作。在大多数情况下,我能够避免在
tests
目录中为我的应用程序设置子目录,只需设置
test\u cases='..
(允许我遵循在应用程序文件夹中设置tests.py的惯例)。回答得很好!这适用于django 3.1.5。我将print(“running reusableapp tests…”)放在可重用应用程序tests.py的顶部,以便查看正在运行哪些测试。