django - सेजरी के लिए डीजेन्गा टेस्ट केस डेटाबेस बनाओ




testing celery (2)

जब एक Django परीक्षा का मामला चलता है, तो यह एक पृथक परीक्षण डेटाबेस बनाता है, ताकि प्रत्येक परीक्षण पूर्ण होने पर डेटाबेस लिखते हों। मैं सेलेरी के साथ एकीकरण परीक्षण बनाने की कोशिश कर रहा हूं, लेकिन मैं यह नहीं जान सकता कि अजवाइन टेस्ट डाटाबेस को कैसे सेलेरी से कनेक्ट करना है। सरल सेटअप में, Django में बचाए गए ऑब्जेक्ट सेलेरी के लिए अदृश्य होते हैं और सेलरी में बचाए गए ऑब्जेक्ट अनिश्चित काल तक जारी रहते हैं

यहां एक उदाहरण परीक्षण का मामला है:

import json
from rest_framework.test import APITestCase
from myapp.models import MyModel
from myapp.util import get_result_from_response

class MyTestCase(APITestCase):
    @classmethod
    def setUpTestData(cls):
        # This object is not visible to Celery
        MyModel(id='test_object').save()

    def test_celery_integration(self):
        # This view spawns a Celery task
        # Task should see MyModel.objects.get(id='test_object'), but can't
        http_response = self.client.post('/', 'test_data', format='json')

        result = get_result_from_response(http_response)
        result.get()  # Wait for task to finish before ending test case
        # Objects saved by Celery task should be deleted, but persist

मेरे पास दो प्रश्न हैं:

  1. यह कैसे करें कि सेलरी ऑब्जेक्ट्स देख सकता है कि डीजेंगो टेस्ट केस?

  2. मैं कैसे यह सुनिश्चित कर सकता हूं कि परीक्षण पूर्ण होने के बाद सेरीरी द्वारा बचाए गए सभी ऑब्जेक्ट स्वचालित रूप से वापस लाए जाते हैं?

मैं ऑब्जेक्ट को मैन्युअल रूप से साफ़ करने के लिए तैयार हूं, अगर यह स्वचालित रूप से संभव नहीं है, लेकिन tearDown भी tearDown में ऑब्जेक्ट्स का एक विलोपन वापस APISimpleTestCase जा रहा है।


आपके unittests के लिए मैं अजवाइन निर्भरता को छोड़ने की अनुशंसा करता हूं, दो निम्नलिखित लिंक आपको अपने यूनिट्स शुरू करने के लिए निसानारी इन्फोस प्रदान करेगा:

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


जेगों टेस्ट केस के अंदर एक सीलरी कार्यकर्ता शुरू करने से यह संभव है

पृष्ठभूमि

Django का स्मृति-स्मृति डेटाबेस sqlite3 है चूंकि यह स्क्लिट इन-मेमरी डाटाबेस के विवरण पृष्ठ पर बताता है , "ए-मेमरी डेटाबेस को साझा करने के लिए [ए] लॉन्च करने वाले डेटाबेस कनेक्शन को एक ही प्रक्रिया में होना चाहिए।" इसका अर्थ यह है कि, जब तक डीजां एक इन-मेमोरी टेस्ट डेटाबेस का उपयोग करता है और एक अलग प्रक्रिया में सेरीरी शुरू हो जाती है, तो यह एक मौलिक रूप से असंभव है कि सलेरी और डीजेन्गो एक टेस्ट डेटाबेस का हिस्सा हो।

हालांकि, celery.contrib.testing.worker.start_worker साथ, एक समान प्रक्रिया के भीतर एक अलग धागे में एक celery.contrib.testing.worker.start_worker कार्यकर्ता शुरू करने के लिए संभव है यह कार्यकर्ता इन-मेमरी डाटाबेस का उपयोग कर सकता है।

यह मानता है कि अजवाइन जेगो परियोजना के साथ पहले से ही सामान्य तरीके से सेटअप कर रहा है।

उपाय

क्योंकि डीजेंगो-सेलेरी में कुछ क्रॉस-थ्रेड कम्युनिकेशन शामिल है, केवल परीक्षण मामलों को अलग-अलग लेनदेन में नहीं चलेंगे जो काम करेंगे। परीक्षण के मामले को सीधे SimpleTestCase या इसके बाकी समकक्ष APISimpleTestCase से प्राप्त करना चाहिए और क्लास विशेषता allow_database_queries को True सेट करना चाहिए।

चाबी setUpClass की setUpClass विधि में setUpClass कार्यकर्ता को शुरू करना है और उसे tearDownClass विधि में बंद करना है। मुख्य फ़ंक्शन celery.contrib.testing.worker.start_worker(app) , जिसे वर्तमान सेलेरी एप की एक आवृत्ति की आवश्यकता है, संभवतः mysite.celery.app से प्राप्त की गई है और एक पायथन __enter__ रिटर्न देता है, जिसमें __enter__ और __exit__ विधियां हैं, जो कि setUpClass और tearDownClass setUpClass में setUpClass tearDownClass , क्रमशः। संभवत: डेकोरेटर या कुछ चीज़ों के साथ ContextManager को मैन्युअल रूप से प्रवेश करने और मौजूदा से बचने का एक तरीका है, लेकिन मैं इसे समझ नहीं सका। यहां एक उदाहरण है tests.py फ़ाइल:

from celery.contrib.testing.worker import start_worker
from django.test import SimpleTestCase

from mysite.celery import app

class BatchSimulationTestCase(SimpleTestCase):
    allow_database_queries = True

    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        # Start up celery worker
        cls.celery_worker = start_worker(app)
        cls.celery_worker.__enter__()

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()

        # Close worker
        cls.celery_worker.__exit__(None, None, None)

    def test_my_function(self):
        # my_task.delay() or something

जो भी कारण से, परीक्षण कर्मचारी 'celery.ping' नामक कार्य का उपयोग करने की कोशिश करता है, शायद कर्मचारी विफलता के मामले में बेहतर त्रुटि संदेश प्रदान करने के लिए। यहां तक ​​कि perform_ping_check को एक start_worker तर्क के रूप में False करने के लिए सेट करें ओटी start_worker अभी भी उसके अस्तित्व के लिए परीक्षण करता है वह कार्य है जो कि celery.contrib.testing.tasks.ping । हालांकि, यह कार्य डिफ़ॉल्ट रूप से स्थापित नहीं है celery.contrib.testing . celery.contrib.testing को INSTALLED_APPS जोड़कर यह कार्य प्रदान करना संभव है। हालांकि, यह केवल यह कार्यकर्ता को दिखाई देता है; कार्यकर्ता को उत्पन्न कोड नहीं कार्यकर्ता उत्पन्न करने वाला कोड assert 'celery.ping' in app.tasks करता है, जो विफल रहता है। यह टिप्पणी करने से सबकुछ काम होता है, लेकिन एक स्थापित लाइब्रेरी को संशोधित करना एक अच्छा समाधान नहीं है मैं शायद कुछ गलत कर रहा हूं, लेकिन जिस वैकल्पिक हल पर मैंने तय किया है, वह साधारण फ़ंक्शन की प्रतिलिपि है, कहीं इसे app.autodiscover_tasks() द्वारा app.autodiscover_tasks() जा सकता है। app.autodiscover_tasks() , जैसे celery.py :

@app.task(name='celery.ping')
def ping():
    # type: () -> str
    """Simple task that just returns 'pong'."""
    return 'pong'

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