Django-celery के साथ इकाई परीक्षण?


82

मैं हमारी django-celery परियोजना के लिए एक परीक्षण पद्धति के साथ आने की कोशिश कर रहा हूं । मैंने दस्तावेज में नोट्स पढ़े हैं , लेकिन इसने मुझे यह अंदाजा नहीं दिया कि वास्तव में क्या करना है। मैं वास्तविक डेमों में कार्यों के परीक्षण के बारे में चिंतित नहीं हूं, बस अपने कोड की कार्यक्षमता । मुख्य रूप से मैं सोच रहा हूँ:

  1. हम task.delay()परीक्षण के दौरान बाईपास कैसे कर सकते हैं (मैंने सेटिंग की कोशिश की CELERY_ALWAYS_EAGER = Trueलेकिन इससे कोई फर्क नहीं पड़ा)?
  2. हम वास्तव में हमारी सेटिंग्स को बदलने के बिना अनुशंसित परीक्षण सेटिंग्स का उपयोग कैसे करते हैं (यदि वह सबसे अच्छा तरीका है)?
  3. क्या हम अभी भी उपयोग कर सकते हैं manage.py testया क्या हमें एक कस्टम धावक का उपयोग करना है?

कुल मिलाकर अजवाइन के साथ परीक्षण के लिए कोई संकेत या सुझाव बहुत उपयोगी होगा।


1
आप क्या मतलब CELERY_ALWAYS_EAGERहै कोई फर्क नहीं पड़ता?
आस्कोल

मैं अभी भी खरगोशों के संपर्क में नहीं आने के बारे में त्रुटियां प्राप्त करता हूं।
जेसन वेब

क्या आपके पास ट्रेसबैक है? मुझे लगता है कि .delayएक कनेक्शन स्थापित करने की कोशिश करने के अलावा कुछ और हो सकता है।
अक्सोल

11
सेटिंग BROKER_BACKEND=memoryउस मामले में मदद कर सकती है।
आस्कोल 3'10

पूछो तो सही थे। BROKER_BACKEND=memoryठीक कर दिया। यदि आप इसे उत्तर के रूप में रखते हैं तो मैं इसे सही करूँगा।
जेसन वेब

जवाबों:


43

सेटिंग का प्रयास करें:

BROKER_BACKEND = 'memory'

( Askol की टिप्पणी के लिए धन्यवाद ।)


8
मेरा मानना ​​है कि CELERY_ALWAYS_EAGER सेट होने पर यह आवश्यक नहीं है।
1

3
क्या आपने अजवाइन 4 के लिए एक समाधान खोजा?
डेविड शुमान

72

मुझे उन परीक्षणों पर ओवरराइड_सेटिंग्स डेकोरेटर का उपयोग करना पसंद है जिन्हें पूरा करने के लिए अजवाइन के परिणामों की आवश्यकता होती है।

from django.test import TestCase
from django.test.utils import override_settings
from myapp.tasks import mytask

class AddTestCase(TestCase):

    @override_settings(CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
                       CELERY_ALWAYS_EAGER=True,
                       BROKER_BACKEND='memory')
    def test_mytask(self):
        result = mytask.delay()
        self.assertTrue(result.successful())

यदि आप इसे सभी परीक्षणों में लागू करना चाहते हैं, तो आप अजवाइन परीक्षण धावक का उपयोग कर सकते हैं जैसा कि http://docs.celeryproject.org/en/2.5/django/unit-testing.html पर वर्णित है, जो मूल रूप से इन समान सेटिंग्स को सेट करता है ()BROKER_BACKEND = 'memory' ) ।

सेटिंग्स में:

TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'

CeleryTestSuiteRunner के स्रोत को देखें और यह स्पष्ट है कि क्या हो रहा है।


1
यह अजवाइन 4 के साथ काम नहीं किया, यहां तक कि से क्षेत्र renames साथ यहाँ
shadi

अजवाइन 3.1 पर काम करता है। मेरे पास मेरे सेलेरी टेस्ट के मामले हैं, जो इस डेकोरेटर के साथ एक मूल वर्ग से प्राप्त होते हैं। इस तरह यह केवल एक ही स्थान पर आवश्यक है और इसमें खींचने की कोई आवश्यकता नहीं है djcelery
14

1
यह सेलेरी 4.4 पर शानदार काम करता है। और Django 2.2। यूनिट परीक्षण चलाने के लिए सबसे अच्छा तरीका, कि मैं अभी तक आया हूं।
एरिक कालकोकेन

18

यहाँ मेरे परीक्षण बेस क्लास का एक अंश है जो apply_asyncविधि को स्टब्स करता है और कॉल को रिकॉर्ड करता है (जिसमें शामिल हैं Task.delay।) यह थोड़ा सकल है, लेकिन यह पिछले कुछ महीनों से मेरी ज़रूरतों को पूरा करने में कामयाब रहा है जो मैं इसका उपयोग कर रहा हूं।

from django.test import TestCase
from celery.task.base import Task
# For recent versions, Task has been moved to celery.task.app:
# from celery.app.task import Task
# See http://docs.celeryproject.org/en/latest/reference/celery.app.task.html

class CeleryTestCaseBase(TestCase):

    def setUp(self):
        super(CeleryTestCaseBase, self).setUp()
        self.applied_tasks = []

        self.task_apply_async_orig = Task.apply_async

        @classmethod
        def new_apply_async(task_class, args=None, kwargs=None, **options):
            self.handle_apply_async(task_class, args, kwargs, **options)

        # monkey patch the regular apply_sync with our method
        Task.apply_async = new_apply_async

    def tearDown(self):
        super(CeleryTestCaseBase, self).tearDown()

        # Reset the monkey patch to the original method
        Task.apply_async = self.task_apply_async_orig

    def handle_apply_async(self, task_class, args=None, kwargs=None, **options):
        self.applied_tasks.append((task_class, tuple(args), kwargs))

    def assert_task_sent(self, task_class, *args, **kwargs):
        was_sent = any(task_class == task[0] and args == task[1] and kwargs == task[2]
                       for task in self.applied_tasks)
        self.assertTrue(was_sent, 'Task not called w/class %s and args %s' % (task_class, args))

    def assert_task_not_sent(self, task_class):
        was_sent = any(task_class == task[0] for task in self.applied_tasks)
        self.assertFalse(was_sent, 'Task was not expected to be called, but was.  Applied tasks: %s' %                 self.applied_tasks)

यहाँ एक "सिर के ऊपर से" उदाहरण है कि आप इसे अपने परीक्षण मामलों में कैसे उपयोग करेंगे:

mymodule.py

from my_tasks import SomeTask

def run_some_task(should_run):
    if should_run:
        SomeTask.delay(1, some_kwarg=2)

test_mymodule.py

class RunSomeTaskTest(CeleryTestCaseBase):
    def test_should_run(self):
        run_some_task(should_run=True)
        self.assert_task_sent(SomeTask, 1, some_kwarg=2)

    def test_should_not_run(self):
        run_some_task(should_run=False)
        self.assert_task_not_sent(SomeTask)

4

चूँकि मैं अभी भी इसे खोज परिणामों में देख रहा हूं, सेटिंग्स ओवरराइड हो गई हैं

TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'

मेरे लिए सेलेरी डॉक्स के अनुसार काम किया


1

2019 में यहां आने वाले सभी के लिए: अलग-अलग रणनीतियों को कवर करने वाले इस लेख को चेकआउट करें , जिसमें कार्यों को समकालिक रूप से शामिल करना शामिल है।


1

यह जो मैंने किया है

मेरे पास myapp.tasks.py मेरे पास है:

from celery import shared_task

@shared_task()
def add(a, b):
    return a + b

मेरे पास myapp.test_tasks.py मेरे पास है:

from django.test import TestCase, override_settings
from myapp.tasks import add


class TasksTestCase(TestCase):

    def setUp(self):
        ...

    @override_settings(CELERY_TASK_ALWAYS_EAGER=True,CELERY_TASK_EAGER_PROPOGATES=True)
    def test_create_sections(self):
        result= add.delay(1,2)
        assert result.successful() == True
        assert result.get() == 3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.