2017-06-29 11 views
7

django-cacheops का उपयोग करके, मैं यह जांचना चाहता हूं कि मेरे विचार कैश हो रहे हैं क्योंकि मैं उनका इरादा रखता हूं। मेरे टेस्ट केस में मैं कैशॉप cache_read को एक हैंडलर से सिग्नल कर रहा हूं जो हिट या मिस के लिए कैश में मान बढ़ाएगा। हालांकि, सिग्नल कभी नहीं निकाल दिया जाता है। क्या किसी टेस्टकेस में एक डीजेंगो सिग्नल हैंडलर को जोड़ने के लिए सही तरीके से पता है, पूरी तरह से उस टेस्टकेस में उपयोग के लिए?परीक्षणों में django सिग्नल हैंडलर को कनेक्ट करना

यहाँ क्या मैं अब तक

from cacheops.signals import cache_read 

cache.set('test_cache_hits', 0) 
cache.set('test_cache_misses', 0) 

def cache_log(sender, func, hit, **kwargs): 
    # never called 
    if hit: 
     cache.incr('test_cache_hits') 
    else: 
     cache.incr('test_cache_misses') 


class BootstrapTests(TestCase): 

    @classmethod 
    def setUpClass(cls): 
     super(BootstrapTests, cls).setUpClass() 
     cache_read.connect(cache_log) 
     assert cache_read.has_listeners() 

    def test_something_that_should_fill_and_retrieve_cache(self): 
     .... 
     hits = cache.get('test_cache_hits') # always 0 

मैं भी मॉड्यूल स्तर पर संकेत हैंडलर जोड़ने की कोशिश की है है है, और नियमित रूप से testcase setUp विधि में, एक ही परिणाम के साथ सभी।

संपादित करें: यहाँ मेरी वास्तविक परीक्षा कोड है, के साथ साथ वस्तु मैं परीक्षण कर रहा हूँ। मैं फ़ंक्शन कैश करने के लिए cached_as सजावट का उपयोग कर रहा हूं। यह परीक्षण वर्तमान में विफल रहा है।

boostrap.py

class BootstrapData(object): 

    def __init__(self, app, person=None): 
     self.app = app 

    def get_homepage_dict(self, context={}): 

     url_name = self.app.url_name 

     @cached_as(App.objects.filter(url_name=url_name), extra=context) 
     def _get_homepage_dict(): 
      if self.app.homepage is None: 
       return None 

      concrete_module_class = MODULE_MAPPING[self.app.homepage.type] 
      serializer_class_name = f'{concrete_module_class.__name__}Serializer' 
      serializer_class = getattr(api.serializers, serializer_class_name) 
      concrete_module = concrete_module_class.objects.get(module=self.app.homepage) 
      serializer = serializer_class(context=context) 
      key = concrete_module_class.__name__ 
      return { 
       key: serializer.to_representation(instance=concrete_module) 
      } 
     return _get_homepage_dict() 

test_bootstrap.py

class BootstrapDataTest(TestCase): 

    def setUp(self): 
     super(BootstrapDataTest, self).setUp() 

     def set_signal(signal=None, **kwargs): 
      self.signal_calls.append(kwargs) 
     self.signal_calls = [] 
     cache_read.connect(set_signal, dispatch_uid=1, weak=False) 
     self.app = self.setup_basic_app() # creates an 'App' model and saves it 

    def tearDown(self): 
     cache_read.disconnect(dispatch_uid=1) 

    def test_boostrap_data_is_cached(self): 

     obj = BootstrapData(self.app) 
     obj.get_homepage_dict() 

     # fails, self.signal_calls == [] 
     self.assertEqual(self.signal_calls, [{'sender': App, 'func': None, 'hit': False }]) 

     self.signal_calls = [] 

     obj.get_homepage_dict() 
     self.assertEqual(self.signal_calls, [{'sender': App, 'func': None, 'hit': True}]) 
+1

क्या आप वाकई सुनिश्चित हैं कि परीक्षण 'कैश_read' सिग्नल ट्रिगर करेंगे? कैशॉप 'कैश_read' सिग्नल को ट्रिगर नहीं करने वाला कोई भी कैश नहीं पढ़ेगा। https://github.com/Suor/django-cacheops/blob/master/cacheops/query.py cachops पैकेज वे एक परीक्षण जहां वे 'setUp' विधि में एक संकेत कनेक्ट का एक उदाहरण है में भी । https://github.com/Suor/django-cacheops/blob/daa907d6ec5dc98d5cc80a3d519469fb134bd0bb/tests/tests.py#L917 – ARJMP

+1

मैं गलत हो सकता है लेकिन django-cacheops क्वेरीसमूहों और नियमित रूप से नहीं कुंजी कैश करने के लिए बनाया गया है। इसलिए, 'cache_read' सिग्नल को तब तक नहीं बुलाया जाएगा जब आप जिस मान को प्राप्त करने का प्रयास कर रहे हैं वह क्वेरीसेट नहीं है। – mattjegan

+0

आप शायद कैशॉप अनुरोध नहीं करते हैं या कभी भी हिट नहीं करते हैं। आपको अपना टेस्ट कोड देना चाहिए। – Suor

उत्तर

0

इस विशिष्ट मामले में, यह पता चला कि मेरे परीक्षण के मामलों में डीजेंगो के बाकी ढांचे के एपीआईटीएस्टकेस को उप-वर्गीकृत किया गया है, जो बदले में django के SimpleTestCase subclasses।

cacheops स्रोतों में देख, मैंने पाया कि उन परीक्षण उपवर्ग TransactionTestCase, और परीक्षण का मामला यह समस्या ठीक से स्विच।

जानना चाहता है कि यह मामला है, लेकिन इस मुद्दे को अब के लिए हल किया जाता है रुचि रखते हैं।

+0

ऐसा इसलिए है क्योंकि 'SimpleTestCase' प्रत्येक परीक्षण को लेन-देन में लपेटता है और कैशॉप गंदे होने के बाद लेनदेन में बंद हो जाता है। ऐसा इसलिए है क्योंकि लेनदेन के भीतर से दिखाई देने वाला डीबी राज्य अलग है और इसे कैश नहीं किया जाना चाहिए और न ही कैश पर भरोसा करना चाहिए। – Suor

+0

आह, स्पष्टीकरण के लिए धन्यवाद – bharling

1

मैं नहीं देख सकते हैं क्यों यह हो रहा है, लेकिन मैं वैसे भी एक उपयोगी जवाब बनाने की कोशिश करेंगे।

सबसे पहले, आप कैश से काम करता है कि क्या आप उस की जांच करने के लिए अपने स्वयं के दुष्प्रभाव पर भरोसा नहीं करना चाहिए, और संकेत प्राथमिक कार्य के दुष्प्रभाव होते हैं परीक्षण करने के लिए चाहते हैं - db कॉल को रोकने। कि परीक्षण का प्रयास करें:

def test_it_works(self): 
    with self.assertNumQueries(1): 
     obj.get_homepage_dict() 

    with self.assertNumQueries(0): 
     obj.get_homepage_dict() 

दूसरा, अगर आप को पता है कि हर जगह प्रिंट जोड़ने cacheops कोड सहित में खुदाई और देखो, जहां यह बंद हो जाता है हो सकता है आप हो रहा है चाहता हूँ। वैकल्पिक रूप से, आप मेरे देखने के लिए एक परीक्षण कर सकते हैं, निर्देश यहां https://github.com/Suor/django-cacheops#writing-a-test है।

अंतिम, आपका परीक्षण थोड़ा गलत है। @cached_as() प्रेषक के लिए None होगा और func समारोह को सजाया जाएगा।

+0

मदद के लिए धन्यवाद - कई महीनों बाद वापस आ रहा है, मैंने सीखा है कि ऐसा इसलिए था क्योंकि मेरे परीक्षण के मामलों ने ट्रांज़ेक्शनटेस्टकेस को अपने आधार के रूप में उपयोग नहीं किया था (कैशॉप में परीक्षण के साथ)। टेस्टकेस बेस क्लास को स्विच करना यह सब काम करता है। – bharling

संबंधित मुद्दे