8

I have a simple periodic task:

from celery.decorators import periodic_task
from celery.task.schedules import crontab
from .models import Subscription

@periodic_task(run_every=crontab(minute=0, hour=0))
def deactivate_subscriptions():
    for subscription in Subscription.objects.filter(is_expired=True):
        print(subscription)
        subscription.is_active = False
        subscription.can_activate = False
        subscription.save()

And I want to cover it with tests.

I found information about how to test simple tasks, like @shared_task, but nowhere can I find an example of testing @periodic_task

Narnik Gamarnik
  • 1,049
  • 1
  • 16
  • 35
  • You can call this method as you would call any other method in your unit tests framework... What exactly are you trying to test here? That this task will fire at midnight each day? Or paths within the method? – Greg0ry Mar 31 '18 at 16:57
  • Yes, I want to check whether crontab will work or not. – Narnik Gamarnik Mar 31 '18 at 16:59
  • This should be covered within `celery` own unit tests... I am not sure if you will be able to unit test this mechanism. – Greg0ry Mar 31 '18 at 18:49
  • @NarnikGamarnik Were you able to achieve this? – Yahya Apr 03 '20 at 08:10

2 Answers2

2

When having a periodic task defined with a decorator you can access the crontab configuration the following way:

tasks.py

@periodic_task(
    run_every=(crontab(minute="*/1")),
)
def my_task():
    pass

some file where you need to access it

from .tasks import my_task

crontab = my_task.run_every

hours_when_it_will_run = crontab.hour
minutes_when_it_will_run = crontab.minute
day_of_the_week_when_it_will_run = crontab.day_of_week
day_of_the_month_when_it_will_run = crontab.day_of_month
month_of_year_when_it_will_run = crontab.month_of_year

This way you can access when task will be executed and you check in your test if the expected time is there.

hendrikschneider
  • 1,696
  • 1
  • 14
  • 26
0

Use the function apply(). Documentation for apply().

Nader Alexan
  • 2,127
  • 22
  • 36