class CommandsTests(TestCase): """ Tests that we can both run worker and clear jobs using custom commands. """ def setUp(self): self.cq = CacheQ(name='CacheQTests') def test_run_worker(self): """ Tests that we can run a worker. We will test only with burst mode option. """ self.cq.enqueue(operator.add, 1,2) self.assertEqual(Job.objects.filter(status=Job.PENDING).count(), 1) call_command('cqworker', burst=True, queue_name='CacheQTests') self.assertEqual(Job.objects.filter(status=Job.DONE).count(), 1) def test_clear_jobs(self): """ Tests that we can clear jobs depending on status. """ for status in [Job.PENDING, Job.PENDING, Job.FAILED, Job.FAILED, Job.DONE, Job.DONE]: Job.objects.create(status=status) self.assertEqual(Job.objects.count(), 6) call_command('cqclear', 'failed') self.assertEqual(Job.objects.count(), 4) self.assertFalse(Job.objects.filter(status=Job.FAILED).exists()) call_command('cqclear', 'all', no_input=True) self.assertEqual(Job.objects.count(), 0)
def setUp(self): self.cq = CacheQ(name='CacheQTests')
def setUp(self): self.cq = CacheQ(name='CacheQTests') self.worker = get_worker(queue_name='CacheQTests', worker_name='testworker') _, self.tempfname = tempfile.mkstemp()
class WorkerTests(TestCase): """ Tests cacheq's worker. This worker will poll the message queue and run jobs accordingly, also updating job status and results. """ def setUp(self): self.cq = CacheQ(name='CacheQTests') self.worker = get_worker(queue_name='CacheQTests', worker_name='testworker') _, self.tempfname = tempfile.mkstemp() def test_single_task(self): """ Tests we can process a single task in burst mode. """ job = self.cq.enqueue(operator.add, 1,2) self.worker.run(burst=True) # check job status and result self.assertTrue(job.ready()) self.assertEqual(job.status, Job.DONE) self.assertEqual(job.result, 3) self.assertEqual(type(job.execution_time), float) self.assertTrue(job.execution_time > 0) def test_multiple_tasks(self): """ Tests we can process multiple tasks for a single job in burst mode. """ job = self.cq.enqueue_many([ (operator.add, (2,3), {}), (operator.div, (5,float(2)), {})]) self.worker.run(burst=True) # check job status and results self.assertTrue(job.ready()) self.assertEqual(job.status, Job.DONE) self.assertEqual(job.result, [5, 2.5]) def test_complex_tasks(self): """ Tests that we can add a series of tasks that depend on each other, which will be run in order. Also, multiple jobs will be submitted. """ job1 = self.cq.enqueue_many([ (task1, (self.tempfname, 'Hello world!'), {}), (task2, (self.tempfname, 'Hello world!'), {})]) job2 = self.cq.enqueue(operator.add, 3,3) self.worker.run(burst=True) # check job status and response self.assertTrue(job1.ready()) self.assertEqual(job1.status, Job.DONE) self.assertEqual(job1.result, [None, None]) self.assertTrue(job2.ready()) self.assertEqual(job2.status, Job.DONE) self.assertEqual(job2.result, 6) def test_exception(self): """ Tests that jobs can handle exceptions properly. """ job = failtask.delay() self.worker.run(burst=True) # let's check status and traceback self.assertTrue(job.ready()) self.assertEqual(job.status, Job.FAILED) self.assertEqual(job.result, None) self.assertTrue('raise Exception("Custom exception")' in job.traceback) self.assertFalse(job.running) def tearDown(self): # remove tempfile os.remove(self.tempfname)
def setUp(self): self.cq = CacheQ('CacheQTests')
class CacheQTests(TestCase): """ Tests that we can create a CacheQ object that manages job placement. """ def setUp(self): self.cq = CacheQ('CacheQTests') def test_enqueue(self): """ Tests that we can enqueue jobs using CacheQ.enqueue. """ self.cq.enqueue(operator.add, 1, 2) # check if a Job object was created self.assertEqual(Job.objects.count(), 1) job = Job.objects.all()[0] task = job.pop_task() self.assertEqual(operator.add, task[0]) # JSON field won't store tuples, so we need # to take that into account for args self.assertEqual([1, 2], task[1]) self.assertEqual({}, task[2]) self.assertEqual(job.status, Job.PENDING) self.assertEqual(job.running, False) # no more tasks in job self.assertEqual(job.pop_task(), None) # check if message queue was signaled self.assertEqual(self.cq.queue.pop_message(), job.uuid) def test_enqueue_many(self): """ Tests that we can enqueu a list of tasks using the following syntax: sqobj.enqueue_many([(func1, args1, kwargs1), (func2, args2, kwargs2), ...]) """ # JSON field will not store tuples, only lists # so we need to take that into account for args tasks = [(operator.add, [1,2], {}), (operator.div, [], {'a': 2, 'b': 2})] self.cq.enqueue_many(tasks) # only one job was created self.assertEqual(Job.objects.count(), 1) job = Job.objects.all()[0] # test tasks are equal for task in tasks: test_iter = zip(task, job.pop_task()) for item in test_iter: self.assertEqual(*item) # no more tasks are available self.assertEqual(job.pop_task(), None) # check if message queue was signaled self.assertEqual(self.cq.queue.pop_message(), job.uuid) def test_job_decorator(self): """ Tests that we can enqueu a function by calling func.delay(*args, **kwargs), which will create a Job with one task and return the job instance. """ decorated = self.cq.job(operator.div) decorated.delay(1,b=2) # this should have created one job self.assertEqual(Job.objects.count(), 1) job = Job.objects.all()[0] task = job.pop_task() self.assertEqual(task[0], operator.div) self.assertEqual(task[1], [1]) self.assertEqual(task[2], {'b': 2}) # no more tasks self.assertEqual(job.pop_task(), None) # check if message queue was signaled self.assertEqual(self.cq.queue.pop_message(), job.uuid) # try with decorated myfunc myfunc.delay(2,3) self.assertEqual(Job.objects.count(), 2) job = Job.objects.all()[1] task = job.pop_task() self.assertEqual(task[0], myfunc) self.assertEqual(task[1], [2,3]) self.assertEqual(task[2], {}) self.assertEqual(job.pop_task(), None) # check if message queue was signaled self.assertEqual(self.cq.queue.pop_message(), job.uuid)