Context Utilities¶
Tools for managing the Behave context: automatic dumps on failure and scoped attribute cleanup.
Context dump on failure¶
When a scenario fails, dump_context() writes every JSON-serializable context attribute to a file for post-mortem debugging.
- behave_kit.context.dump.dump_context(context: Context, path: str | Path = 'debug/') Path[source]¶
Write every JSON-serializable attribute of
contextto a file.Non-serializable attributes are skipped with a logging.warning.
- Returns:
The path of the written file.
- behave_kit.context.dump.dump_context_on_failure(context: Context, scenario: object, path: str | Path = 'debug/') Path | None[source]¶
Call dump_context only when
scenario.statusis"failed".
Examples¶
Automatic (via `setup()`):
from behave_kit import setup
def before_all(context):
setup(context, env="staging")
# Context dump on failure is wired automatically.
# Failed scenarios produce a JSON file in debug/.
Manual:
from behave_kit import dump_context_on_failure
def after_scenario(context, scenario):
dump_context_on_failure(context, scenario, path="debug/")
Always dump (not just on failure):
from behave_kit import dump_context
def after_scenario(context, scenario):
dump_context(context, path="debug/")
Output format¶
The dump file is named after the scenario and contains all serializable attributes:
{
"base_url": "https://example.com",
"status_code": 500,
"user": {"name": "Alice", "age": 30},
"tags": ["browser", "api"]
}
Non-serializable attributes (e.g. WebDriver instances, file handles) are skipped with a warning.
Scoped attributes¶
The @scoped decorator tracks context attributes and automatically deletes them after the scenario, preventing leaks between scenarios.
- behave_kit.context.scoped.scoped(name: str, scope: Scope = Scope.SCENARIO) Callable[[Callable[[Concatenate[Context, P]], R]], Callable[[Concatenate[Context, P]], R]][source]¶
Decorator: track
context.<name>so it is cleaned up automatically.After the wrapped step function runs,
nameis registered for cleanup at the givenscope(see cleanup_scoped).
- behave_kit.context.scoped.cleanup_scoped(context: Context, scope: Scope = Scope.SCENARIO) None[source]¶
Delete every attribute tracked with @scoped at the given
scope.
Examples¶
Basic usage:
from behave_kit import scoped
@scoped("driver")
@when("I start the driver")
def step(context):
context.driver = start_driver()
# context.driver is automatically deleted after the scenario
Multiple scoped attributes:
@scoped("browser")
@scoped("session")
@when("I start a browser session")
def step(context):
context.browser = start_browser()
context.session = create_session()
Feature-scoped attributes:
from behave_kit import scoped, Scope
@scoped("database", scope=Scope.FEATURE)
@given("I have a database connection")
def step(context):
context.database = connect_to_database()
# context.database is cleaned up after all scenarios in the feature
Manual cleanup:
from behave_kit import cleanup_scoped
def after_scenario(context, scenario):
cleanup_scoped(context) # delete all scenario-scoped attributes
Why scoped attributes matter¶
Without @scoped, attributes set in one scenario survive into the next:
# Scenario 1
@when("I create a temporary file")
def step(context):
context.temp_file = create_temp_file()
# Scenario 2 (temp_file still exists from Scenario 1!)
@then("no temp file should exist")
def step(context):
assert not hasattr(context, "temp_file") # FAILS without @scoped
With @scoped:
@scoped("temp_file")
@when("I create a temporary file")
def step(context):
context.temp_file = create_temp_file()
# temp_file is deleted after Scenario 1, so Scenario 2 passes