def create_conditional_step(action_function, **tags): """Factory to create a Step that acts like a guard to a branch. If this step fails, all subsequent steps in that branch, will be skipped. Consider the following trail where 'b' is the "conditional" step. +--> d -->+ +--> b -->| |-->+ | +--> e -->+ | a -->| |--> f +--> c --------------- >+ Lets say we want the branch "b" to run only if some condition is matched. We can consider the step 'b' to be the 'conditional' for this branch, i.e., it should succeed only if the condition is satisfied. If the condition is not satisfied, it will fail. Failure of 'b' will have the effect of skipping the progeny i.e., if 'b' fails, steps d and e will be "skipped". Progeny here is strict i.e., progeny of 'b' are 'd' and 'e' but not 'f' (since 'f' has a parent that is not related to 'b'). This is done by setting two of the step's attributes: Step.pause_on_fail = True -- So that the step fails instead of being moved to Step.PAUSE. Step.skip_progeny_on_failure = True -- So that the progeny are skipped on failure. Returns: Step object whose pause_on_fail is False and skip_progeny_on_failure is True. """ step = Step(action_function, **tags) step.pause_on_fail = False step.skip_progeny_on_failure = True return step
def test_step_manager_with_unset_pause_on_fail(self): def action_function(trail_env, context): raise Exception('test exception') return 'test return value' step = Step(action_function) step.tags[ 'n'] = 7 # Typically this is set automatically. We're setting this manually for testing purposes. step.pause_on_fail = False step.result_queue = MagicMock() trail_environment = MagicMock() step_manager(step, trail_environment, context='foo') expected_result = StepResult(result=Step.FAILURE, return_value='test exception') step.result_queue.put.assert_called_once_with(expected_result)