सेलेरी प्रलेखन में सेलेरी के परीक्षण का उल्लेख किया गया है, लेकिन अगर आप Django का उपयोग नहीं कर रहे हैं, तो एक अजवाइन कार्य का परीक्षण कैसे करें, यह नहीं बताता। आप यह कैसे करते हैं?
सेलेरी प्रलेखन में सेलेरी के परीक्षण का उल्लेख किया गया है, लेकिन अगर आप Django का उपयोग नहीं कर रहे हैं, तो एक अजवाइन कार्य का परीक्षण कैसे करें, यह नहीं बताता। आप यह कैसे करते हैं?
जवाबों:
वहाँ किसी भी unittest lib का उपयोग करके समकालिक रूप से कार्यों का परीक्षण करना संभव है। अजवाइन के कार्यों के साथ काम करते समय मैं 2 अलग-अलग परीक्षण सत्र करता हूं। पहला वाला (जैसा कि मैं सुझाव दे रहा हूं) पूरी तरह से समकालिक है और ऐसा होना चाहिए जो यह सुनिश्चित करता है कि एल्गोरिथ्म वही करता है जो उसे करना चाहिए। दूसरा सत्र पूरी प्रणाली (ब्रोकर सहित) का उपयोग करता है और यह सुनिश्चित करता है कि मुझे क्रमबद्धता मुद्दे या कोई अन्य वितरण, संचार समस्या नहीं है।
इसलिए:
from celery import Celery
celery = Celery()
@celery.task
def add(x, y):
return x + y
और आपका परीक्षण:
from nose.tools import eq_
def test_add_task():
rst = add.apply(args=(4, 4)).get()
eq_(rst, 8)
उम्मीद है की वो मदद करदे!
celery.loader.import_default_modules()
।
मैं इसका उपयोग करता हूं:
with mock.patch('celeryconfig.CELERY_ALWAYS_EAGER', True, create=True):
...
डॉक्स: http://docs.celeryproject.org/en/3.1/configuration.html#celery-aler-nger
CELERY_ALWAYS_EAGER आपको अपने कार्य को सिंक्रोनाइज़ करने देता है, और आपको अजवाइन सर्वर की आवश्यकता नहीं है।
ImportError: No module named celeryconfig
।
celeryconfig.py
किसी के पैकेज में मौजूद है। Docs.celeryproject.org/en/latest/getting-started/… देखें ।
add
एक TestCase
कक्षा के भीतर ओपी के प्रश्न से कार्यों को शुरू करने के लिए एक पूर्ण उदाहरण प्रदान कर सकते हैं ?
CELERY_TASK_ALWAYS_EAGER
यूनिट परीक्षण के लिए 4.0 डॉक्सेज के आधिकारिक अधिकार का उपयोग करता है ।
निर्भर करता है कि वास्तव में आप क्या परीक्षण करना चाहते हैं।
import unittest
from myproject.myapp import celeryapp
class TestMyCeleryWorker(unittest.TestCase):
def setUp(self):
celeryapp.conf.update(CELERY_ALWAYS_EAGER=True)
# conftest.py
from myproject.myapp import celeryapp
@pytest.fixture(scope='module')
def celery_app(request):
celeryapp.conf.update(CELERY_ALWAYS_EAGER=True)
return celeryapp
# test_tasks.py
def test_some_task(celery_app):
...
from celery import current_app
def send_task(name, args=(), kwargs={}, **opts):
# https://github.com/celery/celery/issues/581
task = current_app.tasks[name]
return task.apply(args, kwargs, **opts)
current_app.send_task = send_task
अजवाइन 4 पर उन लोगों के लिए:
@override_settings(CELERY_TASK_ALWAYS_EAGER=True)
क्योंकि सेटिंग्स के नाम बदल दिए गए हैं और अपग्रेड करने का विकल्प चुनने पर अपडेट करने की जरूरत है, देखें
सेलेरी 3.0 के रूप में , DjangoCELERY_ALWAYS_EAGER
में सेट करने का एक तरीका है:
from django.test import TestCase, override_settings
from .foo import foo_celery_task
class MyTest(TestCase):
@override_settings(CELERY_ALWAYS_EAGER=True)
def test_foo(self):
self.assertTrue(foo_celery_task.delay())
अजवाइन v4.0 के बाद से , py.test जुड़नार केवल परीक्षण के लिए अजवाइन कार्यकर्ता शुरू करने के लिए प्रदान किए जाते हैं और जब भी बंद होते हैं:
def test_myfunc_is_executed(celery_session_worker):
# celery_session_worker: <Worker: gen93553@gnpill.local (running)>
assert myfunc.delay().wait(3)
Http://docs.celeryproject.org/en/latest/userguide/testing.html#py-test पर वर्णित अन्य जुड़नार के बीच , आप celery_config
इस तरह से स्थिरता को फिर से परिभाषित करके अजवाइन के डिफ़ॉल्ट विकल्पों को बदल सकते हैं :
@pytest.fixture(scope='session')
def celery_config():
return {
'accept_content': ['json', 'pickle'],
'result_serializer': 'pickle',
}
डिफ़ॉल्ट रूप से, परीक्षण कर्मचारी इन-मेमोरी ब्रोकर और परिणाम बैकएंड का उपयोग करता है। विशिष्ट विशेषताओं का परीक्षण नहीं करने पर स्थानीय रेडिस या रैबिटमक्यू का उपयोग करने की आवश्यकता नहीं है।
pytest का उपयोग करते हुए संदर्भ ।
def test_add(celery_worker):
mytask.delay()
यदि आप फ्लास्क का उपयोग करते हैं, तो एप्लिकेशन कॉन्फिगर सेट करें
CELERY_BROKER_URL = 'memory://'
CELERY_RESULT_BACKEND = 'cache+memory://'
और में conftest.py
@pytest.fixture
def app():
yield app # Your actual Flask application
@pytest.fixture
def celery_app(app):
from celery.contrib.testing import tasks # need it
yield celery_app # Your actual Flask-Celery application
मेरे मामले में (और मैं कई अन्य लोगों को मानता हूं), मैं चाहता था कि किसी भी काम का आंतरिक तर्क pytest का उपयोग करके किया जाए।
टी एल; डॉ; सब कुछ खत्म कर दिया ( विकल्प 2 )
उदाहरण उपयोग मामला :
proj/tasks.py
@shared_task(bind=True)
def add_task(self, a, b):
return a+b;
tests/test_tasks.py
from proj import add_task
def test_add():
assert add_task(1, 2) == 3, '1 + 2 should equal 3'
लेकिन, चूंकि shared_task
डेकोरेटर अजवाइन के आंतरिक तर्क का एक बहुत कुछ करता है, यह वास्तव में एक इकाई परीक्षण नहीं है।
तो, मेरे लिए, 2 विकल्प थे:
विकल्प 1: आंतरिक तर्क अलग करें
proj/tasks_logic.py
def internal_add(a, b):
return a + b;
proj/tasks.py
from .tasks_logic import internal_add
@shared_task(bind=True)
def add_task(self, a, b):
return internal_add(a, b);
यह बहुत ही अजीब लगता है, और इसे कम पठनीय बनाने के अलावा, इसे मैन्युअल रूप से उन विशेषताओं को निकालने और पास करने की आवश्यकता होती है जो अनुरोध का हिस्सा हैं, उदाहरण के लिए task_id
यदि आपको इसकी आवश्यकता है, जो तर्क को कम शुद्ध बनाते हैं।
विकल्प 2: नकली
अजवाइन के पत्तों का मजाक उड़ाता है
tests/__init__.py
# noinspection PyUnresolvedReferences
from celery import shared_task
from mock import patch
def mock_signature(**kwargs):
return {}
def mocked_shared_task(*decorator_args, **decorator_kwargs):
def mocked_shared_decorator(func):
func.signature = func.si = func.s = mock_signature
return func
return mocked_shared_decorator
patch('celery.shared_task', mocked_shared_task).start()
जो तब मुझे अनुरोध ऑब्जेक्ट (फिर से, जैसे आईडी, या रिट्रीस काउंटर, अनुरोध से चीजों की आवश्यकता होती है) का मजाक उड़ाने की अनुमति देता है।
tests/test_tasks.py
from proj import add_task
class MockedRequest:
def __init__(self, id=None):
self.id = id or 1
class MockedTask:
def __init__(self, id=None):
self.request = MockedRequest(id=id)
def test_add():
mocked_task = MockedTask(id=3)
assert add_task(mocked_task, 1, 2) == 3, '1 + 2 should equal 3'
यह समाधान बहुत अधिक मैनुअल है, लेकिन, यह मुझे नियंत्रण देता है कि मुझे वास्तव में यूनिट टेस्ट करने की आवश्यकता है , खुद को दोहराए बिना और अजवाइन के दायरे को खोए बिना।