'Runs each step in the given list of steps.
Returns a tuple of five lists:
- The full set of steps executed
- The steps that passed
- The steps that failed
- The steps that were undefined
- The reason for each failing step (indices matching per above)'

@staticmethod
def run_all(steps, outline=None, run_callbacks=False, ignore_case=True, failfast=False, display_steps=True, reasons_to_fail=None):

    all_steps = []
    steps_passed = []
    steps_failed = []
    steps_undefined = []
    if (reasons_to_fail is None):
        reasons_to_fail = []
    for step in steps:
        if outline:
            step = step.solve_and_clone(outline, display_steps)
        try:
            step.pre_run(ignore_case, with_outline=outline)
            if run_callbacks:
                call_hook('before_each', 'step', step)
            call_hook('before_output', 'step', step)
            if ((not steps_failed) and (not steps_undefined)):
                step.run(ignore_case)
                steps_passed.append(step)
        except NoDefinitionFound as e:
            steps_undefined.append(e.step)
        except Exception as e:
            steps_failed.append(step)
            reasons_to_fail.append(step.why)
            if failfast:
                raise
        finally:
            all_steps.append(step)
            call_hook('after_output', 'step', step)
            if run_callbacks:
                call_hook('after_each', 'step', step)
    return (all_steps, steps_passed, steps_failed, steps_undefined)
