【问题标题】:unittest celery task assertRaisesunittest celery 任务 assertRaises
【发布时间】:2017-01-12 20:04:39
【问题描述】:

我有一些芹菜任务。我想通过 unittest 对其进行测试。

我正在做一些非常相似的事情:

class TestMe(unittest.TestCase):
    def test_celery_task(self):
        self.assertRaises(ValueError, celery_task.apply, args)

对我来说有什么奇怪的:

这个断言失败,因为ValueError not raised,但是在执行过程中我可以看到 ValueError 作为这个 celery 任务的结果。

我不确定,但看起来 assert 的检查速度快于 ValueError 的上升速度。 是否可以检查执行的芹菜任务的结果? 或者如何测试?

【问题讨论】:

    标签: python unit-testing celery assert


    【解决方案1】:

    这不可能。当您将 Celery 任务排入队列时,所发生的一切就是您将消息放入队列以供单独的进程提取;正是该进程运行任务并可能引发异常。

    如果你想检查任务本身是否引发了 ValueError,那么你应该调用任务,而不是延迟函数:

    self.assertRaises(ValueError, celery_task, args)
    

    【讨论】:

    • 这个 celery 任务是在本地运行还是添加到我的队列中?
    • coo,如果在本地。看起来它对我有用。遇到新的错误,如果不是意外执行celery任务,我会接受你的方法
    【解决方案2】:

    我在这里看到 3 个选项。

    1) 尝试在 apply() 上调用 get()。以下是您将获得的:

    class TestMe(unittest.TestCase):
        def test_celery_task(self):
            self.assertRaises(ValueError, celery_task.apply().get(), args)
    

    2) 您可以通过将 'task_always_eager' 设置为 True 来启用 Eager 模式,但这并不能保证您的代码能够赶上。

    3) 更好的选择是模拟 celery 任务。从单元测试的角度来看,用 celery 等系统的实际“活动”部分测试代码单元实际上是不正确的。 这是取自 celery testing documentation 的代码示例。

    from pytest import raises
    
    from celery.exceptions import Retry
    
    # for python 2: use mock.patch from `pip install mock`.
    from unittest.mock import patch
    
    from proj.models import Product
    from proj.tasks import send_order
    
    class test_send_order:
    
        @patch('proj.tasks.Product.order')  # < patching Product in module above
        def test_success(self, product_order):
            product = Product.objects.create(
                name='Foo',
            )
            send_order(product.pk, 3, Decimal(30.3))
            product_order.assert_called_with(3, Decimal(30.3))
    
        @patch('proj.tasks.Product.order')
        @patch('proj.tasks.send_order.retry')
        def test_failure(send_order_retry, product_order):
            product = Product.objects.create(
                name='Foo',
            )
    
            # set a side effect on the patched method
            # so that it raises the error we want.
            product_order.side_effect = OperationalError()
    
            with raises(Retry):
                send_order(product.pk, 3, Decimal(30.6))
    

    【讨论】:

    • 这是集成测试的一部分,这就是为什么我要测试我的系统,而不是模拟 :)
    • 尝试第一个选项。 .get() 应该适用于您的情况
    猜你喜欢
    • 2013-07-09
    • 2011-05-18
    • 1970-01-01
    • 2021-01-30
    • 2018-06-03
    • 1970-01-01
    • 2019-11-08
    • 2014-11-04
    • 2020-04-06
    相关资源
    最近更新 更多