Подтвердить что ты не робот

Как запустить тесты для приложения для повторного использования django?

Могу ли я запускать тесты для своего многоразового приложения Django без включения этого приложения в проект?

В моем приложении используются некоторые модели, поэтому необходимо предоставить настройки (TEST_)DATABASE_*. Где я должен хранить их и как мне запускать тесты?

Для проекта Django я могу запускать тесты с помощью manage.py test; когда я использую django-admin.py test с моим автономным приложением, я получаю:

Ошибка: настройки не могут быть импортированы, потому что переменная среды DJANGO_SETTINGS_MODULE undefined.

Каковы лучшие практики здесь?

4b9b3361

Ответ 1

Я закончил с таким решением (он был вдохновлен решением, найденным в django-голосовании):

Создать файл, например. 'runtests.py' в файле dir, содержащий:

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. Он не требует установленных зависимостей (например, buildout), и это не вредит испытаниям, когда приложение включено в более крупный проект.

Ответ 2

Правильное использование тестового бегуна 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)

DjangoTestSuiteRunner и DiscoverRunner имеют в основном совместимые интерфейсы.

Для получения дополнительной информации обратитесь к документам "Определение тестового Runner":

Ответ 3

Для 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, так же, как python3 foo/tests/runtests.py.

Решение, представленное здесь, довольно многократно используется, нужно только настроить имя приложения foo (и, при необходимости, дополнительные приложения). Они не могут быть установлены с помощью modify_settings, поскольку это пропустит настройку базы данных.

Необходимы следующие файлы:

urls.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 = []

runtests.py

#!/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)

Некоторые параметры являются необязательными; они улучшают скорость или более реалистичную среду.

Второй аргумент указывает на текущий каталог. Он использует функцию для предоставления пути к каталогу для обнаружения тестов ниже этого каталога.

Ответ 4

Для моего многоразового приложения (django-moderation) Я использую buildout. Я создаю example_project, я использую его с buildout для запуска тестов на нем. Я просто помещаю свое приложение в настройки example_project.

Когда я хочу установить все зависимости, используемые моим проектом и запускать тесты, мне нужно сделать следующее:

  • Запуск: python bootstrap.py
  • Запуск сборки:

    бен/Buildout

  • Запустите тесты для Django 1.1 и Django 1.2:

    бен/тест-1,1 бен/тест-1.2

Здесь вы можете найти руководство по настройке приложения многократного использования для использования buildout для развертывания и запуска тестов: http://jacobian.org/writing/django-apps-with-buildout/

Здесь вы найдете пример buildout config, который я использую в своем проекте:

http://github.com/dominno/django-moderation/blob/master//buildout.cfg