Harness recipe: capture_events

It’s a common pattern to test what events are emitted on a charm, to count them, or to verify that some event sequences are activated in unittests. Also you may want to check that the events have the expected API (e.g. that a custom event has a specific attribute…).

For that I wrote two little helper functions that temporarily monkey patch Framework.emit to grab all events being fired on the charm during a test.

You can do for example:

with capture_events(harness.charm, (RelationBrokenEvent, StorageEvent)) as captured:
    harness.update_relation_data(0, 'remote', {'url': 'http://foo.bar'})
assert len(captured) == 2  # 2 events fired
assert isinstance(captured[0], RelationBrokenEvent)

Often you want to check a specific event has been fired: capture() will check for you that exactly one event of a given type has been emitted in that frame.

with capture(harness.charm, UrlReadyEvent) as captured:
    harness.update_relation_data(0, 'remote',
                                 {'ingress': yaml.safe_dump({'url': url})})
event = captured.event
assert event.url == "foo.bar"

To start using these, do:

charmcraft fetch-lib charms.harness_extensions.v0.capture_events (source)

2 Likes

Update: as part of a workshop today, I published this utility as a charm lib! You can now fetch it and give it a try with

charmcraft fetch-lib charms.harness_extensions.v0.capture_events

1 Like

This library is amazing! It is helping a lot, specially when creating new charm libraries to emit and handle custom events.

1 Like