2014-02-28 25 views
6

我想在我的Django應用程序中爲一些芹菜任務編寫一些單元測試。這些任務以模型ID爲參數,做一些事情並更新模型。當運行一個devserver和芹菜工作者時,一切都很好,但是當運行我的測試時,很明顯celery任務沒有使用作爲測試運行的一部分被創建和銷燬的django測試數據庫。問題是,我怎麼能讓芹菜使用與我的其他測試一樣的臨時數據庫?如您所見,我正在使用在類似問題的每個答案中建議的設置覆蓋。讓芹菜使用Django測試數據庫

更新:發現,而不是將對象ID傳遞給任務,並讓任務從數據庫獲取它,如果我只是簡單地將對象本身傳遞給任務,測試正常工作,顯然沒有對運行的負面影響任務。至少現在,這將是我的修復。

在我的測試:

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() 
+1

但是,在任務中傳遞對象本身可能會帶來副作用,例如恢復曾經保存過的數據等。這仍然是你的解決方案還是你有另一種解決方案? – Jonathan

回答

1

有你的代碼中沒有明顯的問題。你不需要運行芹菜工。使用這些設置,芹菜將同步運行任務,並且實際上不會向您的消息隊列發送任何內容。

因爲每個測試都包含在一個事務中,所以即使它們連接到同一個數據庫(它們不是),事務總是被測試回滾並永遠不會提供給工人。

如果您確實需要這樣做,請查看this stackoverflow answer

+0

我明白了你的觀點,但是Fred Campos的答案實際上展示瞭如何對Celery進行集成測試,這對我來說確實是必須的。 – Marviel

1

我也遇到過類似的問題。以下解決方案是不乾淨但它的工作原理。

  1. 創建一個單獨的Django設置文件,它繼承自主 之一。我們稱之爲integration_testing.py
  2. 你的文件應該是這樣的:
    from .settings import *

    DATABASES = { 'default': { 'ENGINE': '<your engine>', 'NAME': 'test_<your database name>', 'USER': <your db user>, 'PASSWORD': <your db password>, 'HOST': <your hostname>, 'PORT': <your port number>, }

  3. 創建一個shell腳本將設置環境和啓動 芹菜工人:

    #!/usr/bin/env bash

    export DJANGO_SETTINGS_MODULE="YOURPROJECTNAME.settings.integration_testing"

    celery purge -A YOURPROJECTNAME -f && celery worker -A YOURPROJECTNAME -l debug

  4. ,如果你以這種方式配置芹菜上述工作:

    app = Celery('YOURPROJECTNAME')

    app.config_from_object('django.conf:settings', namespace='CELERY')

  5. 在後臺運行的腳本。

  6. 使涉及從TransactionTestCase芹菜繼承(或APITransactionTestCase在Django休息框架)的所有測試

  7. 運行使用芹菜單元測試。任何芹菜任務現在將使用您的測試分貝。並希望最好。

+0

這個解決方案對我很好,但我只是想在一些數據庫中添加** __,以便Celery能夠查看數據庫模型,您必須使用TransactionTestCase或APITransactionTestCase的一些變體._ **這是因爲django使用數據庫交易加快測試。 https://stackoverflow.com/questions/35305997/why-isnt-django-actually-writing-changes-to-test-db – Marviel

0

確保芹菜工作者配置爲使用與測試相同的測試數據庫的一種方法是spawn the Celery worker inside the test itself。這可以通過在TestCasesetUpClass方法中使用celery.contrib.testing.worker.start_worker來完成。

你也必須使用來自Django的一個SimpleTestCaseAPISimpleTestCase從休息,而不是一個普通的TestCase,使芹菜線程和測試線程可以看到的變化是相互作出測試數據庫。這些更改在測試結束時仍會被銷燬,但是在測試之間它們不會被破壞,除非您在tearDown方法中手動銷燬它們。