আপনি কিভাবে একটি সেলারি কাজ পরীক্ষা করে?


106

সেলারি ডকুমেন্টেশনে জ্যাঙ্গোর মধ্যে সিলারি টেস্টিংয়ের উল্লেখ রয়েছে তবে আপনি যদি জ্যাঙ্গো ব্যবহার না করে তবে সেলারি টাস্কটি কীভাবে পরীক্ষা করবেন তা ব্যাখ্যা করে না। তুমি এটা কিভাবে করো?

উত্তর:


61

সেখানে যেকোন ইউনিট লাইব ব্যবহার করে সিঙ্ক্রোনসিভ করে কাজগুলি পরীক্ষা করা সম্ভব। সেলারি কাজের সাথে কাজ করার সময় আমি সাধারণত 2 টি পৃথক পরীক্ষার সেশন করি do প্রথমটি (যেমন আমি বেলো পরামর্শ দিচ্ছি) সম্পূর্ণ সিঙ্ক্রোনাস এবং এটি এমন একটি হওয়া উচিত যা নিশ্চিত করে যে অ্যালগরিদম এটি করা উচিত does দ্বিতীয় সেশনে পুরো সিস্টেমটি (ব্রোকার সহ) ব্যবহার করে এবং নিশ্চিত করে যে আমার সিরিয়ালাইজেশন সমস্যা বা অন্য কোনও বিতরণ, যোগাযোগের সমস্যা নেই।

তাই:

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)

আশা করি এইটি কাজ করবে!


1
এটি HTTPDispatchTask ব্যবহার করে এমন কাজগুলি ছাড়া কাজ করে - ডকস.সেলারিপ্রজেক্ট. org/ en/ latest/ userguide/ remote- tasks.html যেখানে আমাকে সেলারি.conf সেট করতে হবে EL CELERY_ALWAYS_EAGER = সত্য তবে এমনকি সেলারি.conf সেট করেও C সেলারি_আইমপোর্টস = celery.task.http.HttpDispatchTask: ( 'celery.task.http') পরীক্ষা NotRegistered সঙ্গে ব্যর্থ
davidmytton

অদ্ভুত, আপনি কি নিশ্চিত হন যে আপনার কিছু আমদানির সমস্যা নেই? এই পরীক্ষাটি কাজ করে (নোট করুন যে আমি প্রতিক্রিয়াটি নষ্ট করছি যাতে এটি সেলারি কী প্রত্যাশা করে তা ফিরিয়ে দেয়)। এছাড়াও, CELERY_IMPORTS এ সংজ্ঞায়িত মডিউলগুলি শ্রমিক সূচনাকালীন আমদানি করা হবে , যাতে এড়ানোর জন্য আমি আপনাকে কল করার পরামর্শ দিই celery.loader.import_default_modules()
FlaPer87

আমিও তোমাকে দেখে নিতে সুপারিশ করবে এখানে । এটি HTTP অনুরোধকে উপহাস করে। ডুনো জানে যে এটি সাহায্য করে কিনা, আমার ধারণা আপনি কোনও পরিষেবা চালু এবং চলমান পরীক্ষা করতে চান, তাই না?
FlaPer87

52

আমি এটি ব্যবহার:

with mock.patch('celeryconfig.CELERY_ALWAYS_EAGER', True, create=True):
    ...

দস্তাবেজ: http://docs.celeryproject.org/en/3.1/configration.html#celery-always-eager

CELERY_ALWAYS_EAGER আপনাকে আপনার টাস্ক সিঙ্ক্রোনাস চালাতে দেয় এবং আপনার সেলারি সার্ভারের দরকার নেই।


1
আমি মনে করি এটি পুরানো - আমি পেয়েছি ImportError: No module named celeryconfig
দেনিথ

7
আমি বিশ্বাস করি যে উপরেরটি ধরে নিয়েছে যে celeryconfig.pyকারও প্যাকেজে মডিউল বিদ্যমান। ডকস.সিলারিপ্রজেক্ট.আর.এন . / স্লেস্ট / বাজেটিং-স্টার্টড/ … দেখুন ।
কামিল সিন্দি

1
আমি জানি এটি পুরানো তবে আপনি কী ক্লাসের addমধ্যে ওপির প্রশ্ন থেকে কাজগুলি লঞ্চ করবেন তার পুরো উদাহরণ সরবরাহ করতে পারেন TestCase?
ক্রুপস

@ ম্যাক্সচ্রিটিয়েন দুঃখিত, আমি পুরো উদাহরণ সরবরাহ করতে পারি না, যেহেতু আমি আর সেলারি ব্যবহার করি না। আপনার যথেষ্ট খ্যাতি পয়েন্ট থাকলে আপনি আমার প্রশ্নটি সম্পাদনা করতে পারেন। যদি আপনার পর্যাপ্ত পরিমাণ না থাকে, তবে দয়া করে আমাকে জানুন যে আমার এই উত্তরটিতে কপি করা উচিত + কী হবে।
গেটলি

1
@ মিকেন 32 ধন্যবাদ যেহেতু সাম্প্রতিক উত্তরটি আমি যেভাবে সমস্যাটি সমাধান করতে চাইছিলাম তা মোকাবেলা করার জন্য, আমি কেবল একটি মন্তব্য রেখেছিলাম যে 4.0.০ এর অফিসিয়াল ডক্স CELERY_TASK_ALWAYS_EAGERইউনিট পরীক্ষার জন্য ব্যবহারকে নিরুৎসাহিত করে ।
ক্রেসোস্কি

33

আপনি ঠিক কী পরীক্ষা করতে চান তার উপর নির্ভর করে।

  • সরাসরি টাস্ক কোডটি পরীক্ষা করুন। আপনার ইউনিট পরীক্ষাগুলি থেকে "টাস্ক.ডলে (...)" কেবল "টাস্ক (...)" কল করবেন না।
  • CELERY_ALWAYS_EAGER ব্যবহার করুন । এটি আপনাকে "টাস্ক.ডলে (...)" বলার মুহুর্তে আপনার কার্যগুলি তত্ক্ষণাত ডেকে আনবে, যাতে আপনি পুরো পথটি পরীক্ষা করতে পারেন (তবে কোনও অ্যাসিনক্রোনাস আচরণ নয়)।

24

ইউনিট পরীক্ষা

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

22

সিলারি 4 এর জন্য এটি এটি:

@override_settings(CELERY_TASK_ALWAYS_EAGER=True)

কারণ সেটিংসের নামগুলি পরিবর্তন করা হয়েছে এবং আপনি আপগ্রেড করতে পছন্দ করে থাকলে আপডেট করার প্রয়োজন রয়েছে, দেখুন

https://docs.celeryproject.org/en/latest/history/whatsnew-4.0.html?highlight=what%20is%20new#lowercase-setting-names


11
সরকারী দস্তাবেজগুলির মতে , "টাস্ক_লওয়েজ_ইজার" (এর আগে "CELERY_ALWAYS_EAGER") ব্যবহার ইউনিট পরীক্ষার জন্য উপযুক্ত নয়। পরিবর্তে তারা আপনার সেলারি অ্যাপ্লিকেশনটি পরীক্ষা করার আরও কয়েকটি দুর্দান্ত উপায় প্রস্তাব করে।
ক্রেসোস্কি

4
আমি কেবল যুক্ত করব যে আপনি কেন আপনার ইউনিট পরীক্ষাগুলিতে উত্সাহী কাজগুলি না চান তা কারণ আপনি পরীক্ষা করছেন না যেমন পরামিতিগুলির সিরিয়ালাইজেশন যা একবার আপনি উত্পাদন কোড ব্যবহার করার পরে ঘটবে।
damd

15

এর মতো সেলারি 3.0 , সেট করার একটা উপায় CELERY_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())

7

সেলারি যেহেতু 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',
    }

ডিফল্টরূপে, পরীক্ষাকর্মী একটি ইন-মেমরি ব্রোকার এবং ফলাফল ব্যাকএন্ড ব্যবহার করে। নির্দিষ্ট বৈশিষ্ট্যগুলি পরীক্ষা না করা হলে স্থানীয় রেডিস বা রেবিটএমকিউ ব্যবহার করার দরকার নেই।


প্রিয় ডাউনভোটার, আপনি কি ভাগ করে নিতে চান কেন এটি খারাপ উত্তর? আন্তরিক ধন্যবাদ
অ্যালানজডস

2
আমার পক্ষে কাজ করেনি, পরীক্ষার স্যুটটি কেবল স্তব্ধ। আপনি আরও কিছু প্রসঙ্গ সরবরাহ করতে পারেন? (যদিও আমি এখনও ভোট দিইনি;))।
দ্বৈততা_

আমার ক্ষেত্রে আমাকে স্পষ্টভাবে মেমরি ব্রোকার এবং ক্যাশে + মেমরি ব্যাকএন্ডটি ব্যবহার করার জন্য সেলিবির কনফিগ ফিক্সচার সেট করতে হয়েছিল
সানজোগেঞ্জো

5

পাইস্ট ব্যবহার করে রেফারেন্স

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

2

আমার ক্ষেত্রে (এবং আমি আরও অনেককে ধরে নিই), আমি যা চেয়েছিলাম তা হ'ল পাইস্ট ব্যবহার করে কোনও কাজের অভ্যন্তরীণ যুক্তি পরীক্ষা করা।

টি এল; ডিআর; দূরে সবকিছু ঠাট্টা করা শেষ ( অপশন 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'

এই সমাধান অনেক বেশি ম্যানুয়াল, কিন্তু, আমার নিয়ন্ত্রণ আমি আসলে প্রয়োজন দেয় ইউনিট পরীক্ষা, নিজেকে পুনরাবৃত্তি ছাড়া, এবং সেলারি সুযোগ হারানো ছাড়া।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.