단위 테스트를 위해 Django 설정을 재정의하는 간단한 메커니즘이 있습니까? 특정 수의 최신 개체를 반환하는 내 모델 중 하나에 관리자가 있습니다. 반환되는 개체 수는 NUM_LATEST 설정에 의해 정의됩니다.
누군가가 설정을 변경하면 내 테스트가 실패 할 가능성이 있습니다. 설정을 무시 setUp()
하고 나중에 복원 하려면 어떻게 해야 tearDown()
합니까? 그것이 가능하지 않다면 원숭이 패치 방법이나 설정을 모의 할 수있는 방법이 있습니까?
편집 : 다음은 내 관리자 코드입니다.
class LatestManager(models.Manager):
"""
Returns a specific number of the most recent public Articles as defined by
the NEWS_LATEST_MAX setting.
"""
def get_query_set(self):
num_latest = getattr(settings, 'NEWS_NUM_LATEST', 10)
return super(LatestManager, self).get_query_set().filter(is_public=True)[:num_latest]
관리자는 settings.NEWS_LATEST_MAX
쿼리 세트를 분할하는 데 사용 합니다. 는 getattr()
단순히 설정이 존재하지 않아야 기본을 제공하는 데 사용됩니다.
답변
편집 :이 답변은 적은 수의 특정 테스트에 대한 설정을 변경하려는 경우 적용됩니다 .
Django 1.4부터 테스트 중에 설정을 재정의하는 방법이 있습니다.
https://docs.djangoproject.com/en/dev/topics/testing/tools/#overriding-settings
TestCase에는 self.settings 컨텍스트 관리자가 있으며 테스트 메서드 또는 전체 TestCase 하위 클래스에 적용 할 수있는 @override_settings 데코레이터도 있습니다.
이러한 기능은 Django 1.3에 아직 존재하지 않았습니다.
모든 테스트에 대한 설정을 변경하려면 기본 설정 파일에서 설정을로드하고 재정의 할 수있는 별도의 테스트 설정 파일을 만들어야합니다. 다른 답변에는 이에 대한 몇 가지 좋은 접근 방식이 있습니다. 나는 hspander 와 dmitrii의 접근 방식 모두에서 성공적인 변형을 보았습니다 .
답변
UnitTest
인스턴스 속성 설정 및 읽기를 포함 하여 하위 클래스에 대해 원하는 모든 작업을 수행 할 수 있습니다 .
from django.conf import settings
class MyTest(unittest.TestCase):
def setUp(self):
self.old_setting = settings.NUM_LATEST
settings.NUM_LATEST = 5 # value tested against in the TestCase
def tearDown(self):
settings.NUM_LATEST = self.old_setting
그러나 django 테스트 케이스는 단일 스레드로 실행되기 때문에 NUM_LATEST 값을 수정하는 다른 것이 무엇인지 궁금합니다. 만약 그 “다른 것”이 당신의 테스트 루틴에 의해 촉발된다면, 나는 어떤 양의 원숭이 패치가 테스트 자체의 진실성을 무효화하지 않고 테스트를 저장할 것이라고 확신하지 못합니다.
답변
런타임에서 설정 구성을 재정의하는 것이 도움이 될 수 있지만 제 생각에는 테스트를 위해 별도의 파일을 만들어야합니다. 이렇게하면 테스트를위한 많은 구성이 절약되며, 이는 복구 할 수없는 작업 (예 : 스테이징 데이터베이스 정리)을 수행하지 않도록합니다.
테스트 파일이 ‘my_project / test_settings.py’에 있다고 가정하고
settings = 'my_project.test_settings' if 'test' in sys.argv else 'my_project.settings'
manage.py에서. 이렇게하면 실행할 때 python manage.py test
test_settings 만 사용할 수 있습니다. pytest와 같은 다른 테스트 클라이언트를 사용하는 경우 쉽게 pytest.ini에 추가 할 수 있습니다.
답변
--settings
테스트를 실행할 때 옵션 을 전달할 수 있습니다.
python manage.py test --settings=mysite.settings_local
답변
업데이트 : 아래 솔루션은 Django 1.3.x 및 이전 버전에서만 필요합니다. > 1.4의 경우 slinkp의 답변을 참조하십시오 .
테스트에서 설정을 자주 변경하고 Python ≥2.5를 사용하는 경우에도이 방법이 편리합니다.
from contextlib import contextmanager
class SettingDoesNotExist:
pass
@contextmanager
def patch_settings(**kwargs):
from django.conf import settings
old_settings = []
for key, new_value in kwargs.items():
old_value = getattr(settings, key, SettingDoesNotExist)
old_settings.append((key, old_value))
setattr(settings, key, new_value)
yield
for key, old_value in old_settings:
if old_value is SettingDoesNotExist:
delattr(settings, key)
else:
setattr(settings, key, old_value)
그런 다음 다음을 수행 할 수 있습니다.
with patch_settings(MY_SETTING='my value', OTHER_SETTING='other value'):
do_my_tests()
답변
@override_settings
프로덕션 환경과 테스트 환경 구성 사이에 차이가 많지 않은 경우 유용합니다.
다른 경우에는 다른 설정 파일을 사용하는 것이 좋습니다. 이 경우 프로젝트는 다음과 같습니다.
your_project
your_app
...
settings
__init__.py
base.py
dev.py
test.py
production.py
manage.py
따라서 대부분의 설정 base.py
이 있어야하며 다른 파일에서 모든 것을 가져 와서 일부 옵션을 재정의해야합니다. 여기 무슨 test.py
파일이 다음과 같이 표시됩니다
from .base import *
DEBUG = False
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'app_db_test'
}
}
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.MD5PasswordHasher',
)
LOGGING = {}
그런 다음 --settings
@MicroPyramid 응답에서와 같이 옵션 을 지정 하거나 DJANGO_SETTINGS_MODULE
환경 변수를 지정한 다음 테스트를 실행할 수 있습니다.
export DJANGO_SETTINGS_MODULE=settings.test
python manage.py test
답변
일부 doctest를 수정하는 동안이 문제를 발견했습니다 … 완전성을 위해 doctest를 사용할 때 설정을 수정하려면 다른 항목을 가져 오기 전에 변경해야한다는 점을 말씀 드리고 싶습니다.
>>> from django.conf import settings
>>> settings.SOME_SETTING = 20
>>> # Your other imports
>>> from django.core.paginator import Paginator
>>> # etc