Somewhat belatedly (apologies!), some more detailed release notes:
Features
- Support for testing Pebble check events (much nicer support than in Harness!)
- Container exec mocking has more of the functionality that Harness has - in particular, you can match against a command prefix rather than the exact command, and you can inspect a list of the commands that the charm exec’d (along with how that was done: stdin, users, environment, etc)
StoredState
now has some consistency checks
API adjustments
Specifying your event
The biggest change is in how you specify the event to run. Previously, this was either a string or pulled via a State
component like Relation
or you manually made an Event
object. Now, this should feel pretty similar to how you observe events in ops, except that you get better autocomplete and type annotations.
Simple events look like:
ctx.run(ctx.on.start(), State())
And when there’s some additional information that the event needs (that would come from the Juju environment or hook tools) they look like:
ctx.run(ctx.on.relation_changed(my_relation), State())
Action events have this new approach, too, without needing a separate method, like:
ctx.run(ctx.on.action("create-admin"), State())
We’ve also moved the old .manager
into the Context
object itself, so when you need access to the charm, you can do it like this:
with ctx(ctx.on.update_status(), State()) as mgr:
mgr.charm.do_something()
mgr.run()
Goodbye magic numbers
The next biggest change is that the various collections in the State
are frozenset
s instead of list
s. Relations, containers, storages, and so on don’t really have any logical ordering, and the Scenario state should be treated as immutable, so frozenset
is a better fit.
Python doesn’t have a nice frozenset
literal syntax, and we dont’ want people to have to write things like relations=frozenset({rel1, rel2})
, so when you’re constructing the state, you can pass in any iterable type (a list, as before, or tuple, or - ideally - set) and it’ll get converted to a frozenset
for you.
This means no more “magic numbers” in your asserts, like assert state.relations[0].x = y
. Instead, these collections have get_
methods, so you can write things like assert state.get_relation(rel1.id).x = y
.
Keyword arguments
Most of the Scenario classes now expect at least some arguments to be passed as keywords, where there wasn’t really any logical ordering. In most cases, your Scenario tests will have been doing this already.
Simpler secrets
It’s much simpler to test events whose handlers manage Juju secrets - in particular: no more managing revision numbers.
And more
There’s some additional renaming/cleaning-up that’s best read about in the upgrading guide that @ppasotti mentioned, which also has more detailed examples of the above.
Internal improvements of note
- The code blocks in the README are tested (with
tox -e test-readme
), although there are some limitations here.
- We explicitly test against Python 3.12 (3.13 soon!) and stopping testing against Pythons older than 3.8.