Skip to content

Commit 8208d64

Browse files
committed
Some notes to help with testing.
1 parent 46a34cb commit 8208d64

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

docs/guide.rst

+77
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,83 @@ weaknesses of each storage layer.
909909
:py:class:`BlackHoleHuey`
910910
All storage methods are no-ops.
911911

912+
Testing Guidelines
913+
------------------
914+
915+
When testing Huey task-decorated functions, a couple guidelines will make your
916+
life easier.
917+
918+
1. Set your :py:class:`Huey` instance to :ref:`immediate`. Any code that calls
919+
a task will run it synchronously, so it is safe to block on results as well.
920+
2. Unit test individual tasks by using the ``.call_local()`` to call the
921+
underlying function.
922+
923+
Examples:
924+
925+
.. code-block:: python
926+
927+
# Consider the following Huey instance and tasks:
928+
huey = RedisHuey(...)
929+
930+
# Fake database to check side-effects.
931+
database = []
932+
933+
@huey.task()
934+
def add(a, b):
935+
return a + b
936+
937+
@huey.periodic_task(crontab(...))
938+
def run_reports():
939+
global database
940+
database.append(True) # Simulate a side-effect.
941+
942+
# The return values for periodic tasks are discarded when run by the
943+
# Huey consumer. A return value may be helpful for testing, however, so
944+
# in this example we will return something to demonstrate how to test
945+
# our periodic task.
946+
return 42
947+
948+
class TestMyTasks(unittest.TestCase):
949+
def setUp(self):
950+
# Make tasks run synchronously.
951+
huey.immediate = True
952+
953+
def tearDown(self):
954+
huey.immediate = False
955+
956+
def test_task(self):
957+
result_handle = add(3, 4)
958+
self.assertEqual(result_handle.get(), 7)
959+
960+
# Alternatively, you can also:
961+
self.assertEqual(add.call_local(3, 4), 7)
962+
963+
def test_task_exceptions(self):
964+
# We can also test exceptions.
965+
result_handle = add(3, None) # Exception logged, but not raised.
966+
967+
with self.assertRaises(TaskException):
968+
result_handle.get()
969+
970+
with self.assertRaises(TypeError):
971+
# Exception raised directly when using call_local().
972+
add.call_local(3, None)
973+
974+
def test_periodic_task(self):
975+
# We cannot use the result-handle from a periodic task, because the
976+
# results are always discarded by the consumer. In this case it is
977+
# necessary to use `.call_local()` if we want to check the return
978+
# value.
979+
self.assertEqual(run_reports.call_local(), 42)
980+
self.assertTrue(len(database), 1)
981+
982+
# If our periodic task has a side-effect, however, we can call it
983+
# normally and check the side-effect happened. For example, if the
984+
# run_reports() periodic task wrote a row to a database, we could
985+
# do something like:
986+
run_reports()
987+
self.assertTrue(len(database), 2)
988+
912989
Tips and tricks
913990
---------------
914991

0 commit comments

Comments
 (0)