1616 make_mock_stage ,
1717 assert_callback_failed ,
1818 assert_callback_succeeded ,
19+ UnhandledException ,
1920)
2021
2122logging .basicConfig (level = logging .INFO )
@@ -130,14 +131,22 @@ def test_failed_operation(self, stage, callback, op):
130131 stage .run_ops_serial (op , callback = callback )
131132 assert_callback_failed (op = op , callback = callback )
132133
133- @pytest .mark .it ("protects the callback with a try/except block" )
134- def test_exception_in_callback (self , stage , mocker , fake_error , op ):
135- callback = mocker .Mock (side_effect = fake_error )
134+ @pytest .mark .it (
135+ "handles Exceptions raised in the callback and passes them to the unhandled error handler"
136+ )
137+ def test_callback_throws_exception (self , stage , mocker , fake_exception , op ):
138+ callback = mocker .Mock (side_effect = fake_exception )
136139 stage .run_ops_serial (op , callback = callback )
137140 assert callback .call_count == 1
138141 assert callback .call_args == mocker .call (op )
139142 assert stage .unhandled_error_handler .call_count == 1
140- assert stage .unhandled_error_handler .call_args == mocker .call (fake_error )
143+ assert stage .unhandled_error_handler .call_args == mocker .call (fake_exception )
144+
145+ @pytest .mark .it ("Allows any BaseExceptions raised in the callback to propagate" )
146+ def test_callback_throws_base_exception (self , stage , mocker , fake_base_exception , op ):
147+ callback = mocker .Mock (side_effect = fake_base_exception )
148+ with pytest .raises (UnhandledException ):
149+ stage .run_ops_serial (op , callback = callback )
141150
142151
143152@pytest .mark .describe ("PipelineStage run_ops_serial function with one op and finally op" )
@@ -196,14 +205,24 @@ def test_callback_with_error_if_op_fails_and_finally_op_succeeds(
196205 stage .run_ops_serial (op , finally_op = finally_op , callback = callback )
197206 assert_callback_failed (callback = callback , op = finally_op , error = op .error )
198207
199- @pytest .mark .it ("protects the callback with a try/except block" )
200- def test_exception_in_callback (self , stage , op , finally_op , fake_error , mocker ):
201- callback = mocker .Mock (side_effect = fake_error )
208+ @pytest .mark .it (
209+ "handles Exceptions raised in the callback and passes them to the unhandled error handler"
210+ )
211+ def test_callback_raises_exception (self , stage , op , finally_op , fake_exception , mocker ):
212+ callback = mocker .Mock (side_effect = fake_exception )
202213 stage .run_ops_serial (op , finally_op = finally_op , callback = callback )
203214 assert callback .call_count == 1
204215 assert callback .call_args == mocker .call (finally_op )
205216 assert stage .unhandled_error_handler .call_count == 1
206- assert stage .unhandled_error_handler .call_args == mocker .call (fake_error )
217+ assert stage .unhandled_error_handler .call_args == mocker .call (fake_exception )
218+
219+ @pytest .mark .it ("Allows any BaseExceptions raised in the callback to propagate" )
220+ def test_callback_raises_base_exception (
221+ self , stage , op , finally_op , fake_base_exception , mocker
222+ ):
223+ callback = mocker .Mock (side_effect = fake_base_exception )
224+ with pytest .raises (UnhandledException ):
225+ stage .run_ops_serial (op , finally_op = finally_op , callback = callback )
207226
208227
209228@pytest .mark .describe ("PipelineStage run_ops_serial function with three ops and without finally op" )
@@ -231,14 +250,22 @@ def test_calls_callback_when_first_op_fails(self, stage, op, op2, op3, callback)
231250 stage .run_ops_serial (op , op2 , op3 , callback = callback )
232251 assert_callback_failed (callback = callback , op = op )
233252
234- @pytest .mark .it ("protects the callback with a try/except block" )
235- def test_exception_in_callback (self , stage , op , op2 , op3 , fake_error , mocker ):
236- callback = mocker .Mock (side_effect = fake_error )
253+ @pytest .mark .it (
254+ "handles Exceptions raised in the callback and passes them to the unhandled error handler"
255+ )
256+ def test_callback_raises_exception (self , stage , op , op2 , op3 , fake_exception , mocker ):
257+ callback = mocker .Mock (side_effect = fake_exception )
237258 stage .run_ops_serial (op , op2 , op3 , callback = callback )
238259 assert callback .call_count == 1
239260 assert callback .call_args == mocker .call (op3 )
240261 assert stage .unhandled_error_handler .call_count == 1
241- assert stage .unhandled_error_handler .call_args == mocker .call (fake_error )
262+ assert stage .unhandled_error_handler .call_args == mocker .call (fake_exception )
263+
264+ @pytest .mark .it ("Allows any BaseExceptions raised in the callback to propagate" )
265+ def test_callback_raises_base_exception (self , stage , op , op2 , op3 , fake_base_exception , mocker ):
266+ callback = mocker .Mock (side_effect = fake_base_exception )
267+ with pytest .raises (UnhandledException ):
268+ stage .run_ops_serial (op , op2 , op3 , callback = callback )
242269
243270 @pytest .mark .it ("runs the second op only after the first op succeeds" )
244271 def test_runs_second_op_after_first_op_succceeds (self , mocker , stage , op , op2 , op3 , callback ):
@@ -338,12 +365,24 @@ def test_calls_callbacK_with_error_when_first_op_and_finally_op_both_fail(
338365 stage .run_ops_serial (op , op2 , op3 , finally_op = finally_op , callback = callback )
339366 assert_callback_failed (callback = callback , op = finally_op , error = finally_op .error )
340367
341- @pytest .mark .it ("protects the callback with a try/except block" )
342- def test_exception_in_callback (self , stage , op , op2 , op3 , finally_op , fake_error , mocker ):
343- callback = mocker .Mock (side_effect = fake_error )
368+ @pytest .mark .it (
369+ "handles Exceptions raised in the callback and passes them to the unhandled error handler"
370+ )
371+ def test_callback_raises_exception (
372+ self , stage , op , op2 , op3 , finally_op , fake_exception , mocker
373+ ):
374+ callback = mocker .Mock (side_effect = fake_exception )
344375 stage .run_ops_serial (op , op2 , op3 , callback = callback , finally_op = finally_op )
345376 assert stage .unhandled_error_handler .call_count == 1
346- assert stage .unhandled_error_handler .call_args == mocker .call (fake_error )
377+ assert stage .unhandled_error_handler .call_args == mocker .call (fake_exception )
378+
379+ @pytest .mark .it ("Allows any BaseExceptions raised in the callback to propagate" )
380+ def test_callback_raises_base_exception (
381+ self , stage , op , op2 , op3 , finally_op , fake_base_exception , mocker
382+ ):
383+ callback = mocker .Mock (side_effect = fake_base_exception )
384+ with pytest .raises (UnhandledException ):
385+ stage .run_ops_serial (op , op2 , op3 , callback = callback , finally_op = finally_op )
347386
348387 @pytest .mark .it ("runs the second op only after the first op succeeds" )
349388 def test_runs_second_op (self , mocker , stage , op , op2 , op3 , finally_op , callback ):
@@ -488,12 +527,22 @@ def test_calls_private_handle_pipeline_event(self, stage, event, mocker):
488527 assert stage ._handle_pipeline_event .call_count == 1
489528 assert stage ._handle_pipeline_event .call_args == mocker .call (event )
490529
491- @pytest .mark .it ("protects _handle_pipeline_event with a try/except block" )
492- def test_exception_in_provate_handle_pipeline_event (self , stage , event , fake_error , mocker ):
493- stage ._handle_pipeline_event = mocker .Mock (side_effect = fake_error )
530+ @pytest .mark .it (
531+ "handles Exceptions raised in _handle_pipeline_Event and passes them to the unhandled error handler"
532+ )
533+ def test_handle_pipeline_events_raises_exception (self , stage , event , fake_exception , mocker ):
534+ stage ._handle_pipeline_event = mocker .Mock (side_effect = fake_exception )
494535 stage .handle_pipeline_event (event )
495536 assert stage .unhandled_error_handler .call_count == 1
496- assert stage .unhandled_error_handler .call_args == mocker .call (fake_error )
537+ assert stage .unhandled_error_handler .call_args == mocker .call (fake_exception )
538+
539+ @pytest .mark .it ("Allows any BaseExceptions raised in _handle_pipeline_event to propagate" )
540+ def test_handle_pipeline_events_raises_base_exception (
541+ self , stage , event , fake_base_exception , mocker
542+ ):
543+ stage ._handle_pipeline_event = mocker .Mock (side_effect = fake_base_exception )
544+ with pytest .raises (UnhandledException ):
545+ stage .handle_pipeline_event (event )
497546
498547
499548@pytest .mark .describe ("PipelineStage _handle_pipeline_event function" )
@@ -516,12 +565,11 @@ def test_error_if_no_previous_stage(self, stage, event):
516565@pytest .mark .describe ("PipelineStage continue_op function" )
517566class TestPipelineStageContinueOp (object ):
518567 @pytest .mark .it ("completes the op without continuing if the op has an error" )
519- def test_completes_op_with_error (self , mocker , stage , op , fake_error , callback ):
520- op .error = fake_error
568+ def test_completes_op_with_error (self , mocker , stage , op , fake_exception , callback ):
569+ op .error = fake_exception
521570 op .callback = callback
522571 stage .continue_op (op )
523- assert callback .call_count == 1
524- assert callback .call_args == mocker .call (op )
572+ assert_callback_failed (op = op , error = fake_exception )
525573 assert stage .next .run_op .call_count == 0
526574
527575 @pytest .mark .it ("fails the op if there is no next stage" )
@@ -548,20 +596,28 @@ def test_calls_callback_on_success(self, stage, op, callback):
548596 assert_callback_succeeded (op )
549597
550598 @pytest .mark .it ("calls the op callback on failure" )
551- def test_calls_callback_on_error (self , stage , op , callback , fake_error ):
552- op .error = fake_error
599+ def test_calls_callback_on_error (self , stage , op , callback , fake_exception ):
600+ op .error = fake_exception
553601 op .callback = callback
554602 stage .complete_op (op )
555- assert_callback_failed (op = op , error = fake_error )
603+ assert_callback_failed (op = op , error = fake_exception )
556604
557- @pytest .mark .it ("protects the op callback with a try/except handler" )
558- def test_exception_in_callback (self , stage , op , fake_error , mocker ):
559- op .callback = mocker .Mock (side_effect = fake_error )
605+ @pytest .mark .it (
606+ "handles Exceptions raised in operation callback and passes them to the unhandled error handler"
607+ )
608+ def test_op_callback_raises_exception (self , stage , op , fake_exception , mocker ):
609+ op .callback = mocker .Mock (side_effect = fake_exception )
560610 stage .complete_op (op )
561611 assert op .callback .call_count == 1
562612 assert op .callback .call_args == mocker .call (op )
563613 assert stage .unhandled_error_handler .call_count == 1
564- assert stage .unhandled_error_handler .call_args == mocker .call (fake_error )
614+ assert stage .unhandled_error_handler .call_args == mocker .call (fake_exception )
615+
616+ @pytest .mark .it ("Allows any BaseExceptions raised in operation callback to propagate" )
617+ def test_op_callback_raises_base_exception (self , stage , op , fake_base_exception , mocker ):
618+ op .callback = mocker .Mock (side_effect = fake_base_exception )
619+ with pytest .raises (UnhandledException ):
620+ stage .complete_op (op )
565621
566622
567623@pytest .mark .describe ("PipelineStage continue_with_different_op function" )
0 commit comments