Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice of testing django-rq ( python-rq ) in Django

I'll start using django-rq in my project.

Django integration with RQ, a Redis based Python queuing library.

What is the best practice of testing django apps which is using RQ?

For example, if I want to test my app as a black box, after User makes some actions I want to execute all jobs in current Queue, and then check all results in my DB. How can I do it in my django-tests?

like image 470
Oduvan Avatar asked Jul 01 '12 13:07

Oduvan


People also ask

What are the different types of tests in Django?

Intro to Testing in Django. Types of tests. Unit and integration are the two main types of tests: Unit Tests are isolated tests that test one specific function. Integration Tests, meanwhile, are larger tests that focus on user behavior and testing entire applications.

How do I use RQ with Django?

The simplest way of using RQ with Django is to use django-rq. Follow the instructions in the README. In order to use RQ together with Django, you have to start the worker in a “Django context”. Possibly, you have to write a custom Django management command to do so.

What is a unit test in Django web development?

Free Bonus: Click here to get access to a free Django Learning Resources Guide (PDF) that shows you tips and tricks as well as common pitfalls to avoid when building Python + Django web applications. Unit Tests are isolated tests that test one specific function.

What is Django?

Django is a high level framework to build scalable web applications. Django is used by companies like Google, Facebook, Pinterest, Nasa etc... Code quality is very important in software engineering. We've many types of tests but in this tutorial i will cover two of them :


2 Answers

I separated my rq tests into a few pieces.

  1. Test that I'm correctly adding things to the queue (using mocks).
  2. Assume that if something gets added to the queue, it will eventually be processed. (rq's test suite should cover this).
  3. Test, given the correct input, my tasks work as expected. (normal code tests).

Code being tested:

def handle(self, *args, **options):
    uid = options.get('user_id')

    # @@@ Need to exclude out users who have gotten an email within $window
    # days.
    if uid is None:
        uids = User.objects.filter(is_active=True, userprofile__waitlisted=False).values_list('id', flat=True)
    else:
        uids = [uid]

    q = rq.Queue(connection=redis.Redis())

    for user_id in uids:
        q.enqueue(mail_user, user_id)

My tests:

class DjangoMailUsersTest(DjangoTestCase):
    def setUp(self):
        self.cmd = MailUserCommand()

    @patch('redis.Redis')
    @patch('rq.Queue')
    def test_no_userid_queues_all_userids(self, queue, _):
        u1 = UserF.create(userprofile__waitlisted=False)
        u2 = UserF.create(userprofile__waitlisted=False)
        self.cmd.handle()
        self.assertItemsEqual(queue.return_value.enqueue.mock_calls,
                              [call(ANY, u1.pk), call(ANY, u2.pk)])

    @patch('redis.Redis')
    @patch('rq.Queue')
    def test_waitlisted_people_excluded(self, queue, _):
        u1 = UserF.create(userprofile__waitlisted=False)
        UserF.create(userprofile__waitlisted=True)
        self.cmd.handle()
        self.assertItemsEqual(queue.return_value.enqueue.mock_calls, [call(ANY, u1.pk)])
like image 137
Justin Abrahms Avatar answered Nov 04 '22 22:11

Justin Abrahms


I just found django-rq, which allows you to spin up a worker in a test environment that executes any tasks on the queue and then quits.

from django.test impor TestCase
from django_rq import get_worker

class MyTest(TestCase):
    def test_something_that_creates_jobs(self):
        ...                      # Stuff that init jobs.
        get_worker().work(burst=True)  # Processes all jobs then stop.
        ...                      # Asserts that the job stuff is done.
like image 26
saul.shanabrook Avatar answered Nov 04 '22 20:11

saul.shanabrook