@@ -909,6 +909,83 @@ weaknesses of each storage layer.
909
909
:py:class: `BlackHoleHuey `
910
910
All storage methods are no-ops.
911
911
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
+
912
989
Tips and tricks
913
990
---------------
914
991
0 commit comments