[英]Unit testing with django-celery?
I am trying to come up with a testing methodology for our django-celery project. 我正在尝试为我们的django-celery项目提出测试方法。 I have read the notes in the documentation , but it didn't give me a good idea of what to actually do.
我已经阅读了文档中的注释,但它并没有让我对实际操作有什么了解。 I am not worried about testing the tasks in the actual daemons, just the functionality of my code.
我并不担心测试实际守护进程中的任务,只是我的代码的功能。 Mainly I am wondering:
主要是我想知道:
task.delay()
during the test (I tried setting CELERY_ALWAYS_EAGER = True
but it made no difference)? task.delay()
(我尝试设置CELERY_ALWAYS_EAGER = True
但它没有区别)? manage.py test
or do we have to use a custom runner? manage.py test
吗?还是我们必须使用自定义跑步者? Overall any hints or tips for testing with celery would be very helpful. 总的来说,使用芹菜进行测试的任何提示或技巧都会非常有用。
I like to use the override_settings decorator on tests which need celery results to complete. 我喜欢在需要celery结果的测试中使用override_settings装饰器。
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())
If you want to apply this to all tests you can use the celery test runner as described at http://docs.celeryproject.org/en/2.5/django/unit-testing.html which basically sets these same settings except ( BROKER_BACKEND = 'memory'
). 如果你想将它应用于所有测试,你可以使用http://docs.celeryproject.org/en/2.5/django/unit-testing.html中描述的celery测试运行器,它基本上设置了这些相同的设置,除了(
BROKER_BACKEND = 'memory'
)。
In settings: 在设置中:
TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'
Look at the source for CeleryTestSuiteRunner and it's pretty clear what's happening. 看看CeleryTestSuiteRunner的来源,很明显发生了什么。
Here's an excerpt from my testing base class that stubs out the apply_async
method and records to the calls to it (which includes Task.delay
.) It's a little gross, but it's managed to fit my needs over the past few months I've been using it. 这是我的测试基类的一个摘录,
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)
Here's an "off the top of the head" example of how you'd use it in your test cases: 以下是您在测试用例中如何使用它的“头顶”示例:
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)
since I still see this come up in search results, settings override with 因为我仍然看到这出现在搜索结果中,设置覆盖了
TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'
worked for me as per Celery Docs 根据Celery Docs为我工作
对于2019年来到这里的每个人:查看本文涵盖不同的策略,包括同步调用任务。
This is what I did 这就是我做的
Inside myapp.tasks.py I have: 在myapp.tasks.py里面我有:
from celery import shared_task
@shared_task()
def add(a, b):
return a + b
Inside myapp.test_tasks.py I have: 在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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.