Python 让芹菜使用Django测试数据库

Python 让芹菜使用Django测试数据库,python,django,unit-testing,celery,django-celery,Python,Django,Unit Testing,Celery,Django Celery,我正在为我的Django应用程序中的一些芹菜任务编写一些单元测试。这些任务将模型id作为参数,执行一些操作,并更新模型。当运行devserver和芹菜worker时,一切都很好,但是当运行我的测试时,很明显芹菜任务没有使用作为测试运行的一部分创建和销毁的django测试数据库。问题是,我怎样才能让芹菜使用和我其余测试相同的临时数据库 如您所见,我正在使用每个答案中针对类似问题建议的设置覆盖 更新:发现不是将对象id传递给任务,而是让任务从db获取它,如果我只是将对象本身传递给任务,测试工作正常,

我正在为我的Django应用程序中的一些芹菜任务编写一些单元测试。这些任务将模型id作为参数,执行一些操作,并更新模型。当运行devserver和芹菜worker时,一切都很好,但是当运行我的测试时,很明显芹菜任务没有使用作为测试运行的一部分创建和销毁的django测试数据库。问题是,我怎样才能让芹菜使用和我其余测试相同的临时数据库

如您所见,我正在使用每个答案中针对类似问题建议的设置覆盖

更新:发现不是将对象id传递给任务,而是让任务从db获取它,如果我只是将对象本身传递给任务,测试工作正常,显然不会对任务的运行产生不利影响。所以至少现在,这将是我的解决办法

在我的测试中:

class JobTest(TestCase):

    @override_settings(CELERY_ALWAYS_EAGER=True,
                       CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
                       BROKER_BACKEND='memory')
    def test_Job_Complete(self):
        job = models.Job()
        job.save()
        tasks.do_a_thing(job.id)
        self.assertTrue(job.complete)
在我的任务中:

@celery.task
def do_a_thing(job_id):
    job = models.Job.objects.get(pk=job_id)
    bunch_of_things(job)
    job.complete = True
    job.save()

您的代码没有明显的问题。你不需要管理芹菜工人。通过这些设置,芹菜将同步运行任务,并且实际上不会向消息队列发送任何内容

无论如何,您都不能轻松地使用实时芹菜工人运行测试,因为每个测试都包装在一个事务中,因此即使它们连接到同一个数据库(它们不是),事务也总是由测试回滚,并且工人永远无法使用


如果您真的需要这样做,请看。

我也遇到过类似的问题。以下溶液不干净,但有效

  • 创建一个单独的Django设置文件,该文件继承自主目录 一个。我们称之为
    integration\u testing.py
  • 您的文件应如下所示:
    from.settings导入*

    数据库={
    “默认值”:{
    “引擎”:“,
    “名称”:“测试”,
    “用户”:,
    “密码”:,
    “主机”:,
    “端口”:,
    }

  • 创建一个shell脚本,它将设置您的环境并启动 芹菜工人:

    #!/usr/bin/env bash

    export-DJANGO\u SETTINGS\u MODULE=“YOURPROJECTNAME.SETTINGS.integration\u testing”

    芹菜清除-A YOURPROJECTNAME-f&&芹菜工人-A YOURPROJECTNAME-l调试

  • 如果您以这种方式配置芹菜,则上述方法有效:

    app=芹菜('YOURPROJECTNAME')

    app.config\u来自对象('django.conf:settings',namespace='CELERY')

  • 在后台运行脚本

  • 使所有涉及芹菜的测试从TransactionTestCase(或django rest框架中的APITransactionTestCase)继承

  • 运行使用芹菜的单元测试。任何芹菜任务现在都将使用测试数据库。希望一切顺利


  • 保证芹菜工作者配置为使用与测试相同的测试数据库的一种方法是to。这可以通过使用
    TestCase
    setUpClass
    方法中的
    芹菜.contrib.testing.worker.start\u worker
    来完成


    您还必须使用来自Django的
    SimpleTestCase
    或来自Rest的
    APISimpleTestCase
    而不是普通的
    TestCase
    ,以便芹菜线程和测试线程可以看到彼此对测试数据库所做的更改。这些更改在测试结束时仍然会被销毁,但不会被销毁除非您在
    拆卸方法中手动销毁它们,否则将在测试之间运行。

    我发现将以下内容添加到
    conftest.py
    中是有效的:

    from django.conf import settings
    
    ...
    
    @pytest.fixture(scope="session")
    def celery_worker_parameters(django_db_setup):
        assert settings.DATABASES["default"]["NAME"].startswith("test_")
        return {}
    
    诀窍是在这里添加
    django\u db\u设置
    fixture,以便在工人身上启用它

    这是标记有以下内容的测试:

    @pytest.mark.django_db(transaction=True)
    @pytest.mark.celery()
    def test_something(celery_worker):
        ...
    

    但是,在任务中传递对象本身可能会给您带来副作用,例如还原曾经保存过的数据等。这仍然是您的解决方案还是您有其他解决方案?不幸的是,传递对象本身对我不起作用,因为它包含许多字段。m2m字段的内容不会被传输,也不会被传输o正确执行任务。这个解决方案对我来说非常有效,但我只是想补充一点,即对于一些数据库,为了让芹菜看到数据库模型,必须使用TransactionTestCase或ApitTransactionTestCase的一些变体。这是因为django使用数据库事务来加快测试。我明白你的观点,但Fred Campos的回答是ally演示了如何使用Celery进行集成测试,这对于我来说确实是必须的。对不起,您为Celery配置了什么使其不使用DisabledBackend?在我的任务中,我无法对任务调用wait(),错误显示“未配置结果后端”。