Source code for behave_kit.continue_after_failed
"""Continue executing remaining steps after a step fails.
By default, Behave stops a scenario at the first failing step. This module
provides utilities to change that behaviour globally or temporarily.
Usage in ``environment.py``::
from behave_kit import continue_after_failed
def before_all(context):
continue_after_failed(True)
Or as a context manager for temporary activation::
from behave_kit import continue_on_failure
def before_scenario(context, scenario):
if "smoke" in scenario.tags:
context._caf_cm = continue_on_failure()
context._caf_cm.__enter__()
def after_scenario(context, scenario):
cm = getattr(context, "_caf_cm", None)
if cm is not None:
cm.__exit__(None, None, None)
"""
from __future__ import annotations
from collections.abc import Iterator
from contextlib import contextmanager
from behave_kit._core.errors import BehaveKitError
from behave_kit._core.logging import get_logger
logger = get_logger("continue_after_failed")
[docs]
def continue_after_failed(enabled: bool = True) -> None:
"""Set whether scenarios continue executing after a failed step.
Sets the class-level attribute ``Scenario.continue_after_failed_step``
which Behave checks before aborting a scenario on step failure.
Args:
enabled: When ``True``, scenarios keep running remaining steps
even after a step fails. When ``False``, execution stops
at the first failing step (Behave's default).
Raises:
BehaveKitError: If ``enabled`` is not a boolean.
"""
if not isinstance(enabled, bool):
raise BehaveKitError(
f"enabled must be a bool, got {type(enabled).__name__}",
suggestion="Pass True or False explicitly",
)
from behave.model import Scenario
Scenario.continue_after_failed_step = enabled
logger.debug("continue_after_failed_step set to %s", enabled)
[docs]
@contextmanager
def continue_on_failure() -> Iterator[None]:
"""Temporarily enable continue-after-failed for the current block.
Sets ``Scenario.continue_after_failed_step`` to ``True`` on entry and
restores the previous value on exit, even if an exception occurs.
Usage::
with continue_on_failure():
# any scenario that runs while inside this block
# will continue after failed steps
...
"""
from behave.model import Scenario
previous: bool = getattr(Scenario, "continue_after_failed_step", False)
Scenario.continue_after_failed_step = True
try:
yield
finally:
Scenario.continue_after_failed_step = previous