Handlers

The scenario framework provides a service that triggers handlers on events.

Handler registration

First of all, declare your handler function:

def _error(event, data):
    assert isinstance(data, scenario.EventData.Error)
    scenario.logging.debug(f"{event!r} handler called with error {data.error!r}")

Then the handlers may be installed by calling the Handlers.install() method on the scenario.handlers manager:

        scenario.handlers.install(scenario.Event.ERROR, _error)

Tip

The event may be passed as an enum constant or a string.

Using enums is usually a better option in as much as they can be type checked in camparison with simple strings.

The Handlers.install() method has a couple of parameters that specialize the way the handlers live and are triggered:

scenario:

Related scenario, if any.

When this reference is set, the handler will be triggered only if the current scenario is the given scenario.

once:

Once flag.

Makes this scenario be triggered once, and then uninstalled.

first:

Make this handler be called prior to other handlers when the event is met, otherwise the handler is called after the other handlers already registered for the given event.

The handlers may be uninstalled thanks to the Handlers.uninstall() method.

Scenario events

The following tables describes the scenario events that can be used to register handlers for.

Tip

Use the scenario.Event shortcut to the internal ScenarioEvent enum from scenario user code.

Events raised during a scenario execution

Event

Description

Data type

ScenarioEvent.BEFORE_TEST = “scenario.before-test”

Before test handlers: handlers that are executed at the beginning of the scenario.

ScenarioEventData.Scenario

ScenarioEvent.BEFORE_STEP = “scenario.before-step”

Before step handlers: handlers that are executed before each step.

ScenarioEventData.Step

ScenarioEvent.ERROR = “scenario.error”

Error handler: handlers that are executed on test errors.

ScenarioEventData.Error

ScenarioEvent.AFTER_STEP = “scenario.after-step”

After step handlers: handlers that are executed after each step.

ScenarioEventData.Step

ScenarioEvent.AFTER_TEST = “scenario.after-test”

After test handlers: handlers that are executed at the end of the scenario.

ScenarioEventData.Scenario

Events raised during a campaign execution

Event

Description

Data type

ScenarioEvent.BEFORE_CAMPAIGN = “scenario.before-campaign”

Before campaign handlers: handlers that are executed at the beginning of the campaign.

ScenarioEventData.Campaign

ScenarioEvent.BEFORE_TEST_SUITE = “scenario.before-test-suite”

Before test suite handlers: handlers that are executed at the beginning of each test suite.

ScenarioEventData.TestSuite

ScenarioEvent.BEFORE_TEST_CASE = “scenario.before-test-case”

Before test case handlers: handlers that are executed at the beginning of each test case.

ScenarioEventData.TestCase

ScenarioEvent.ERROR = “scenario.error”

Error handler: handlers that are executed on test errors.

ScenarioEventData.Error

ScenarioEvent.AFTER_TEST_CASE = “scenario.after-test-case”

After test case handlers: handlers that are executed after each test case.

ScenarioEventData.TestCase

ScenarioEvent.AFTER_TEST_SUITE = “scenario.after-test-suite”

After test suite handlers: handlers that are executed after each test suite.

ScenarioEventData.TestSuite

ScenarioEvent.AFTER_CAMPAIGN = “scenario.after-campaign”

After campaign handlers: handlers that are executed after the campaign.

ScenarioEventData.Campaign

User events

Even though the handler service is basically provided to let user code react on scenario events, it is made as a general feature so that it can be used for other purposes. This way, you may define your own set of events within your test environment for instance.

In order to do so, a good practice is to define your set of events with an enum, so that they can be type checked.

class UserEvent(enum.Enum):
    FOO = "foo"

Then use the Handlers.callhandlers() method to make the registered handlers (matching their additional conditions in option) be called. Pass on event data as a single objet, which can be whatever you want.

            scenario.handlers.callhandlers(UserEvent.FOO, {"a": 1, "b": "bar"})

Tip

Considering evolutivity concerns, event data should rather be set with:

  • dedicated objects, like ScenarioEventData proposes,

  • or more informal dictionaries, like the ‘demo/handlers.py’ sample does.