2009-05-27 16 views
82

क्या यूनिट परीक्षण के लिए Django सेटिंग्स को ओवरराइड करने के लिए कोई आसान तंत्र है? मेरे पास मेरे मॉडल में से एक पर एक प्रबंधक है जो नवीनतम वस्तुओं की एक विशिष्ट संख्या देता है। इसे लौटने वाली वस्तुओं की संख्या को NUM_LATEST सेटिंग द्वारा परिभाषित किया जाता है।Django में विभिन्न सेटिंग्स के साथ यूनिट परीक्षण कैसे करें?

यदि कोई सेटिंग बदलना चाहता है तो मेरे परीक्षण विफल होने की संभावना है। मैं 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() बस डिफॉल्ट प्रदान करने के लिए उपयोग किया जाता है, सेटिंग मौजूद नहीं है।

+0

@ एंटो - क्या आप समझा सकते हैं कि बेहतर जवाब क्यों दें या प्रदान करें? – user

+0

इस बीच में बदल गया; पूर्व स्वीकृत एक था [यह एक] (http://stackoverflow.com/a/913596/1030960);) – Anto

उत्तर

134

संपादित करें: इस सवाल का जवाब लागू होता है अगर आप चाहते हैं छोटेविशिष्ट परीक्षणों की संख्या बदलने के लिए। https://docs.djangoproject.com/en/dev/topics/testing/tools/#overriding-settings

testcase एक self.settings संदर्भ प्रबंधक होगा, और वहाँ भी एक @override_settings डेकोरेटर है कि या तो एक परीक्षण करने के लिए लागू किया जा सकता हो जाएगा:

Django 1.4 के बाद से, परीक्षण के दौरान सेटिंग को ओवरराइड करने के लिए तरीके देखते हैं विधि या एक संपूर्ण टेस्टकेस उपclass।

ये सुविधाएं अभी तक Django 1.3 में मौजूद नहीं थीं।

यदि आप के लिए सभी के लिए सेटिंग्स बदलना चाहते हैं, तो आप परीक्षण के लिए एक अलग सेटिंग्स फ़ाइल बनाना चाहते हैं, जो आपकी मुख्य सेटिंग्स फ़ाइल से सेटिंग्स लोड और ओवरराइड कर सकता है।अन्य उत्तरों में इसके लिए कई अच्छे दृष्टिकोण हैं; मैंने hspander's और dmitrii's दोनों दृष्टिकोणों पर सफल विविधताएं देखी हैं।

+4

मैं कहूंगा कि यह अब Django 1.4+ –

+0

में ऐसा करने का सबसे अच्छा तरीका है परीक्षण के भीतर से आप उस सेटिंग को कैसे एक्सेस करते हैं? मैंने पाया है कि कुछ 'self.settings()। Wrapped.MEDIA_ROOT' जैसा है, लेकिन यह बहुत भयानक है। – mlissner

+2

Django के नए संस्करणों के लिए इसके लिए एक विशिष्ट संदर्भ प्रबंधक है: https://docs.djangoproject.com/en/1.8/topics/testing/tools/#overriding-settings – Akhorus

41

आप 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 मान को संशोधित करना? यदि आपके परीक्षण दिनचर्या द्वारा "कुछ और" ट्रिगर किया गया है, तो मुझे यकीन नहीं है कि बंदर पैचिंग की कोई भी राशि परीक्षण की सत्यता को अमान्य किए बिना परीक्षण को सहेज लेगी।

+0

मैंने एक कोड उदाहरण जोड़ा। – Soviut

+0

आह, गॉचा ... कोड उदाहरण इसे साफ़ करता है। –

+0

आपका उदाहरण काम किया। यूनिट परीक्षण के दायरे के मामले में यह एक आंख खोलने वाला है और परीक्षण स्टैक में सेटिंग्स कॉल स्टैक के माध्यम से कैसे फैलती हैं। – Soviut

3

मिले इस जबकि कुछ doctests ठीक करने के लिए ... पूर्णता मुझे लगता है कि आप जब doctests का उपयोग कर सेटिंग्स को संशोधित करने जा रहे हैं, आप इसे कुछ और आयात करने से पहले क्या करना चाहिए उल्लेख के लिए कोशिश कर रहा है ...

>>> from django.conf import settings 

>>> settings.SOME_SETTING = 20 

>>> # Your other imports 
>>> from django.core.paginator import Paginator 
>>> # etc 
19

अद्यतन: नीचे दिया गया समाधान केवल Django 1.3.x और इससे पहले की आवश्यकता है। के लिए 1.4 देखें slinkp's answer

आप अपने परीक्षण में अक्सर सेटिंग में बदलाव और अजगर ≥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() 
+0

यह बहुत अच्छा समाधान है किसी कारण से मेरी सेटिंग्स यूनिट परीक्षणों में ठीक से काम नहीं कर रही थीं। बहुत ही सुरुचिपूर्ण समाधान, साझा करने के लिए धन्यवाद। – Tomas

+0

मैं इस कोड का उपयोग कर रहा हूं, लेकिन मुझे परीक्षण विफलताओं को कैस्केड करने में समस्याएं थीं, क्योंकि प्रश्न में विफल होने पर सेटिंग वापस नहीं आतीं।इसे संबोधित करने के लिए, मैंने 'अंत में 'ब्लॉक में निहित फ़ंक्शन के अंतिम भाग के साथ' उपज 'कथन के चारों ओर एक प्रयास/आखिरकार जोड़ा, ताकि सेटिंग्स हमेशा वापस आ जाए। –

+0

मैं जन्म के लिए जवाब संपादित करूंगा। मुझे उम्मीद है कि मैं यह सही कर रहा हूँ! :) –

9

हालांकि रनटाइम पर सेटिंग कॉन्फ़िगरेशन ओवरराइड करने में सहायता हो सकती है, मेरी राय में आपको परीक्षण के लिए एक अलग फ़ाइल बनाना चाहिए। यह परीक्षण के लिए बहुत सी कॉन्फ़िगरेशन बचाता है और यह सुनिश्चित करेगा कि आप कभी भी अपरिवर्तनीय कुछ नहीं कर रहे हैं (जैसे स्टेजिंग डेटाबेस की सफाई)।

, अपने परीक्षण फ़ाइल 'my_project/test_settings.py' में मौजूद मान लें कि आपका manage.py में जोड़ने

settings = 'my_project.test_settings' if 'test' in sys.argv else 'my_project.settings' 

। यह सुनिश्चित करेगा कि जब आप python manage.py test चलाते हैं तो आप केवल test_settings का उपयोग करते हैं। आप pytest जैसे कुछ अन्य परीक्षण ग्राहक का उपयोग कर रहे हैं, तो आप के रूप में आसानी से इस

7

pytest.ini को जोड़ सकता है आप --settings विकल्प पारित कर सकते हैं जब परीक्षण चल रहा है, तो आप कई ज़रूरत नहीं है

python manage.py test --settings=mysite.settings_local 
+0

यह उन सेटिंग्स को ढूंढना बंद कर दिया जो सेटिंग्स.dev में स्थित हैं जो सेटिंग्स.बेस का विस्तार है – holms

3

@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 = {} 

और फिर आप या तो @MicroPyramid जवाब में के रूप में --settings विकल्प निर्दिष्ट, या DJANGO_SETTINGS_MODULE वातावरण चर निर्दिष्ट करने की आवश्यकता और फिर आप अपने परीक्षण चला सकते हैं:

export DJANGO_SETTINGS_MODULE=settings.test 
python manage.py test 
संबंधित मुद्दे