← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/maas/celery-tests into lp:maas

 

Raphaël Badin has proposed merging lp:~rvb/maas/celery-tests into lp:maas.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rvb/maas/celery-tests/+merge/106639

This branch adds a Celery fixture to be able to test celery tasks properly.  With this fixture, all the tasks will be executed in a synchronous fashion and exceptions raised when running tasks will be re-raised.

= Pre-imp =

Had a pre-imp talk with Gavin about this.  This could have been a new TestCase but since creating a fixture gives us more flexibility (to test Celery task that don't involve Django for instance).

= Notes =

I got completely rid of django-celery that we don't use at all.

I've added "${buildout:directory}/src/maas" to the paths used by test.maas so that Celery can find src/maas/celeryconfig.
-- 
https://code.launchpad.net/~rvb/maas/celery-tests/+merge/106639
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/celery-tests into lp:maas.
=== modified file 'buildout.cfg'
--- buildout.cfg	2012-05-15 13:32:50 +0000
+++ buildout.cfg	2012-05-21 14:48:19 +0000
@@ -27,7 +27,6 @@
   convoy
   dbus
   Django
-  django-celery
   django-picklefield
   South
   amqplib
@@ -85,7 +84,6 @@
   celery
   convoy
   django
-  django-celery
   django-debug-toolbar
   django-nose
   django-piston
@@ -119,6 +117,7 @@
   sys.argv[1:1] = ["test", "--exclude=provisioningserver"]
 scripts = test.maas
 extra-paths =
+  ${buildout:directory}/src/maas
   ${maas:extra-paths}
 
 [pserv]

=== added file 'src/maastesting/celery.py'
--- src/maastesting/celery.py	1970-01-01 00:00:00 +0000
+++ src/maastesting/celery.py	2012-05-21 14:48:19 +0000
@@ -0,0 +1,53 @@
+# Copyright 2012 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""A fixture to make Celery run tasks in a synchronous fashion."""
+
+from __future__ import (
+    absolute_import,
+    print_function,
+    unicode_literals,
+    )
+
+__metaclass__ = type
+__all__ = [
+    'CeleryFixture',
+    ]
+
+from celery import current_app
+from fixtures import Fixture
+from testtools.monkey import MonkeyPatcher
+
+
+class CeleryFixture(Fixture):
+    """This fixture will make Celery run tasks in a synchronous fashion.
+
+    This fixture can be used directly::
+
+    >>> class CeleryTest1(TestCase):
+    >>>
+    >>>     def setUp(self):
+    >>>         super(CeleryTest1, self).setUp()
+    >>>         self.useFixture(CeleryFixture())
+
+    It can also be converted into a FixtureResource::
+
+    >>> from testresources import FixtureResource
+    >>>
+    >>> class CeleryTest2(TestCase):
+    >>>
+    >>>     resources = (
+    >>>         ("celery", FixtureResource(CeleryFixture())),
+    >>>         )
+    >>>
+    """
+
+    def setUp(self):
+        super(CeleryFixture, self).setUp()
+        patcher = MonkeyPatcher()
+        patcher.add_patch(current_app.conf, 'CELERY_ALWAYS_EAGER', True)
+        patcher.add_patch(
+            current_app.conf, 'CELERY_EAGER_PROPAGATES_EXCEPTIONS', True)
+        self.addCleanup(patcher.restore)
+        patcher.patch()
+

=== added file 'src/maastesting/tests/test_celery.py'
--- src/maastesting/tests/test_celery.py	1970-01-01 00:00:00 +0000
+++ src/maastesting/tests/test_celery.py	2012-05-21 14:48:19 +0000
@@ -0,0 +1,56 @@
+# Copyright 2012 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test matchers."""
+
+from __future__ import (
+    absolute_import,
+    print_function,
+    unicode_literals,
+    )
+
+__metaclass__ = type
+__all__ = []
+
+import random
+
+from celery import current_app
+from celery.decorators import task
+from celery.result import EagerResult
+from maastesting.celery import CeleryFixture
+from maastesting.testcase import TestCase
+from testresources import FixtureResource
+
+
+@task()
+def task_add(x, y):
+    return x + y
+
+@task()
+def task_exception(x, y):
+    raise RuntimeError()
+
+
+class TestCeleryFixture(TestCase):
+    """Tests `CeleryFixture`."""
+
+    resources = (
+        ("celery", FixtureResource(CeleryFixture())),
+        )
+
+    def test_celery_config(self):
+        self.assertTrue(getattr(current_app.conf, 'CELERY_ALWAYS_EAGER'))
+        self.assertTrue(
+            getattr(current_app.conf, 'CELERY_EAGER_PROPAGATES_EXCEPTIONS'))
+
+    def test_celery_eagerresult_contains_result(self):
+       # The result is an instance of EagerResult and it contains the actual
+        # result.
+        x = random.randrange(100)
+        y = random.randrange(100)
+        result = task_add.delay(x, y)
+        self.assertIsInstance(result, EagerResult)
+        self.assertEqual(x + y, result.result)
+
+    def test_celery_exception_raised(self):
+        self.assertRaises(RuntimeError, task_exception.delay, 1, 2)

=== modified file 'src/provisioningserver/power/poweraction.py'
--- src/provisioningserver/power/poweraction.py	2012-05-21 05:58:17 +0000
+++ src/provisioningserver/power/poweraction.py	2012-05-21 14:48:19 +0000
@@ -37,7 +37,7 @@
     :param power_type: A value from :class:`POWER_TYPE`.
 
     The class is intended to be used in two phases:
-    1. Instatiation, passing the power_type.
+    1. Instantiation, passing the power_type.
     2. .execute(), passing any template parameters required by the template.
     """
 

=== modified file 'versions.cfg'
--- versions.cfg	2012-05-15 13:32:50 +0000
+++ versions.cfg	2012-05-21 14:48:19 +0000
@@ -20,7 +20,6 @@
 celery = 2.4.6
 convoy = 0.2.2
 dbus = 1.0.0
-django-celery = 2.4.2
 django-picklefield = 0.1.9
 django-piston = 0.2.3
 FormEncode = 1.2.4