Единичное тестирование с использованием джанго-трубопровода
У меня есть проблемы с модульным тестированием представлений приложения, использующего django-конвейер? Всякий раз, когда я выполняю client.get() на любом URL-адресе, он создает следующее исключение:
ValueError: файл css/bootstrap.css не найден с объектом < конвейер .storage.PipelineCachedStorage в 0x10d544950 > .
Тот факт, что это bootstrap.css, конечно, не имеет значения, но что я не могу выполнить рендеринг представления из-за этого исключения.
Приглашаем всех гидов/советов!
Ответы
Ответ 1
У меня возникла аналогичная проблема. Однако установка
STATICFILES_STORAGE='pipeline.storage.NonPackagingPipelineStorage'
при запуске тестов только частично решена моя проблема. Я также должен был полностью отключить конвейер, если вы хотите запустить тесты LiverServerTestCase, не называя "collectcstatic" перед запуском тестов:
PIPELINE_ENABLED=False
Так как django 1.4 довольно легко модифицировать настройки для тестов - есть удобный декоратор, который работает для методов или классов TestCase:
https://docs.djangoproject.com/en/1.6/topics/testing/tools/#overriding-settings
например.
from django.test.utils import override_settings
@override_settings(STATICFILES_STORAGE='pipeline.storage.NonPackagingPipelineStorage', PIPELINE_ENABLED=False)
class BaseTestCase(LiveServerTestCase):
"""
A base test case for Selenium
"""
def setUp(self):
...
Однако это привело к непоследовательным результатам, как описывает @jrothenbuhler в своем ответе. Несмотря на это, это не так идеально, если вы используете интеграционные тесты - вы должны максимально имитировать производство, чтобы поймать любые потенциальные проблемы. Похоже, django 1.7 имеет решение для этого в виде нового тестового примера "StaticLiveServerTestCase". Из документов:
https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#django.contrib.staticfiles.testing.StaticLiveServerCase
Этот подкласс Unittest TestCase расширяется django.test.LiveServerTestCase.
Как и его родитель, вы можете использовать его для написания тестов, которые включают запуская тестируемый код и потребляя его с помощью инструментов тестирования через HTTP (например, Selenium, PhantomJS и т.д.), из-за чего его необходимо, чтобы статические активы также были опубликованы.
Я не тестировал это, но звучит многообещающе. На данный момент я делаю то, что @jrothenbuhler в его решении использует пользовательский тестовый бегун, который не требует, чтобы вы запускали collectstatic. Если вы действительно хотите запустить коллекцию, вы можете сделать что-то вроде этого:
from django.conf import settings
from django.test.simple import DjangoTestSuiteRunner
from django.core.management import call_command
class CustomTestRunner(DjangoTestSuiteRunner):
"""
Custom test runner to get around pipeline and static file issues
"""
def setup_test_environment(self):
super(CustomTestRunner, self).setup_test_environment()
settings.STATICFILES_STORAGE = 'pipeline.storage.NonPackagingPipelineStorage'
call_command('collectstatic', interactive=False)
В settings.py
TEST_RUNNER = 'path.to.CustomTestRunner'
Ответ 2
Я столкнулся с той же проблемой. Я занимался этим с помощью специального тестового бегуна:
from django.conf import settings
from django.test.simple import DjangoTestSuiteRunner
from pipeline.conf import settings as pipeline_settings
class PipelineOverrideRunner(DjangoTestSuiteRunner):
def setup_test_environment(self):
'''Override STATICFILES_STORAGE and pipeline DEBUG.'''
super(PipelineOverrideRunner, self).setup_test_environment()
settings.STATICFILES_STORAGE = 'pipeline.storage.PipelineFinderStorage'
pipeline_settings.DEBUG = True
Затем в вашем settings.py:
TEST_RUNNER = 'path.to.PipelineOverrideRunner'
Настройка параметра DEBUG для конвейера в True означает, что статические файлы не упакованы. Это предотвращает необходимость запуска collectstatic перед запуском тестов. Обратите внимание, что это настройка DEBUG конвейера, а не Django's, которая здесь переопределяется. Причина этого в том, что вы хотите, чтобы Django DEBUG был False при тестировании, чтобы лучше всего имитировать производственную среду.
Настройка STATICFILES_STORAGE в PipelineFinderStorage делает это так, чтобы статические файлы находились, когда для параметра Django DEBUG установлено значение False, как и при выполнении тестов.
Причина, по которой я решил переопределить эти параметры в пользовательском тестовом runner, а не в пользовательской TestCase, состоит в том, что определенные вещи, такие как объект django.contrib.staticfiles.storage.staticfiles_storage, устанавливаются один раз на основе этих и других настройки. При использовании настраиваемой TestCase я столкнулся с проблемами, когда тесты проходили и терпели неудачу в зависимости от того, произошло ли переопределение, когда были загружены модули, такие как django.contrib.staticfiles.storage.
Ответ 3
Я столкнулся с той же проблемой. Мне удалось обойти это, используя другой STATIC_FILES_STORAGE
, когда я тестирую:
STATICFILES_STORAGE = 'pipeline.storage.NonPackagingPipelineStorage'
У меня есть отдельные файлы настроек для производства и тестирования, поэтому я просто поместил его в свою тестовую версию, но если вы этого не сделаете, вы можете, возможно, обернуть его в if DEBUG
.
- EDIT
Потребовалось немного больше усилий, потому что это может присутствовать только во время unittesting. Для этого я использовал фрагмент http://djangosnippets.org/snippets/1011/ и создал класс UITestCase:
class UITestCase(SettingsTestCase):
'''
UITestCase handles setting the Pipeline settings correctly.
'''
def __init__(self, *args, **kwargs):
super(UITestCase, self).__init__(*args, **kwargs)
def setUp(self):
self.settings_manager.set(
STATICFILES_STORAGE='pipeline.storage.NonPackagingPipelineStorage')
Теперь все мои тесты, которые должны отображать пользовательский интерфейс, которые включают теги compress_css, используют UITestCase вместо django.test.TestCase.
Ответ 4
Я столкнулся с той же проблемой, и оказалось, что у меня был
TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'
Я не понимаю, как, но он должен каким-то образом взаимодействовать с Pipeline. Как только я удалил эту настройку, проблема исчезла.
Мне все еще нужно было заставить Сельдерей проявлять нетерпение во время тестирования, поэтому я использовал override_settings
для тестов, которые ему нужны:
from django.test.utils import override_settings
…
class RegisterTestCase(TestCase):
@override_settings(CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
CELERY_ALWAYS_EAGER=True,
BROKER_BACKEND='memory')
def test_new(self):
…
Ответ 5
То же самое здесь. Относится к этим вопросам: https://github.com/cyberdelia/django-pipeline/issues/277
Поскольку я использую py.test, я помещаю это в conftest.py в качестве обходного пути:
import pytest
from django.conf import settings
def pytest_configure():
# workaround to avoid django pipeline issue
# refers to
settings.STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
Ответ 6
я пробовал обходной путь @jrothenbuhler, и сначала это помогает..
но потом, по какой-то причине, он снова начинает работать с той же ошибкой
после нескольких часов отладки я понял, что единственное, что помогает, это установить
STATICFILES_STORAGE = 'pipeline.storage.NonPackagingPipelineStorage'
прямо в настройках...
не знаю почему, но это работает.