Logging and diagnostics

<- Back to home

behave-toolkit intentionally keeps logging small and explicit. Start with one persistent suite log. Move to YAML-defined named loggers only when one file is no longer enough.

Choose the smallest thing that works

Need

Recommended tool

one persistent test-run.log file

configure_test_logging(...)

several named loggers with config-owned paths

YAML logging: section plus configure_loggers(context)

readable cycle progress messages

format_cycle_progress(...) or get_cycle_progress(...)

Upgrade path: named loggers from YAML

Use YAML-defined loggers when you want multiple named outputs, for example one suite log and one diagnostics log.

objects:
  diagnostics_log_path:
    factory: pathlib.Path
    scope: global
    args:
      - $ref: artifacts_path
      - diagnostics.log

logging:
  test_run:
    path:
      $ref: test_log_path
    logger_name: suite-tests
    inject_as: test_logger

  diagnostics:
    path:
      $ref: diagnostics_log_path
    logger_name: suite-diagnostics
    inject_as: diagnostics_logger
    console: false
from pathlib import Path

from behave_toolkit import configure_loggers, install

CONFIG_PATH = Path(__file__).with_name("behave-toolkit.yaml")


def before_all(context):
    install(context, CONFIG_PATH)
    configure_loggers(context)

configure_loggers(context) should run once from before_all(), after global objects are active.

Logging cycle progress

Scenario cycling becomes easier to follow if you log the cycle label in before_scenario().

from behave_toolkit import activate_scenario_scope, format_cycle_progress


def before_scenario(context, scenario):
    activate_scenario_scope(context)
    progress = format_cycle_progress(scenario)
    if progress is None:
        context.test_logger.info("%s", scenario.name)
    else:
        context.test_logger.info("Cycle %s -> %s", progress, scenario.name)

Use get_cycle_progress(...) instead when you want the raw (current_cycle, total_cycles) tuple for assertions or your own formatting.

Runtime inspection

The manager gives you a lightweight way to inspect configured logging state:

def before_all(context):
    install(context, CONFIG_PATH)
    configure_loggers(context)
    print(context.toolkit.list_loggers())
    print(context.toolkit.logger("test_run"))

Practical recommendations

  • Start with configure_test_logging(...) unless you already know you need more than one log file.

  • Keep logger paths as managed objects when you want them to be easy to reuse elsewhere in the suite.

  • Treat YAML-defined named loggers as a scaling tool, not the default recommendation.

  • Remember that logger config is global in this version of the toolkit.

If your logging setup fails because of duplicate names, missing paths, or hook ordering, see Troubleshooting.