Install & Compatibility
Where this runs
tested against v8.7.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.806s · 23.6MB
glibcpy 3.10–3.910 runs
installs and imports cleanly · install 2.2s · import 0.733s · 25MB
22MB installed
● package 22MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Context
✓ from ops.testing import Context
✗ from scenario import Context
'scenario' is not a valid module; the correct import is from ops.testing.
State
✓ from ops.testing import State
✗ from ops.scenario import State
State is part of ops.testing, not a separate ops.scenario module.
CharmSpec
✓ from ops.testing import CharmSpec
CharmSpec is available in ops.testing; no common wrong import.
Minimal test: creates a charm, runs the install event, asserts active status.
import os
import yaml
from ops.charm import CharmBase
from ops.testing import Context, State, CharmSpec
class MyCharm(CharmBase):
def __init__(self, *args):
super().__init__(*args)
self.framework.observe(self.on.install, self._on_install)
def _on_install(self, event):
self.unit.status.set_active()
def test_charm():
metadata = yaml.safe_load('''
name: my-charm
summary: test
series: [focal]
''')
spec = CharmSpec(MyCharm, meta=metadata)
ctx = Context(spec, meta={'name': 'my-charm'}, actions=None, config=None)
state = ctx.run('install', State())
assert state.unit_status.name == 'active'
print('Test passed')
if __name__ == '__main__':
test_charm()
Errors
Common errors & fixes
ImportError: cannot import name 'Context' from 'ops.testing'
ops-scenario not installed or incompatible version; Context moved to ops.testing in v8.
fixInstall with 'pip install ops[testing]' and use 'from ops.testing import Context'.
AttributeError: module 'ops.testing' has no attribute 'State'
Using an older version (pre-3.0) where State was named ScenarioState or not available.
fixUpgrade to latest ops: 'pip install --upgrade ops[testing]'.
pytest.fixture() got an unexpected keyword argument 'scope'
Incorrectly using a fixture decorator with arguments unsupported by pytest (e.g., from ops.testing.fixture).
fixUse the standard pytest fixture decorator: @pytest.fixture, not ops.testing.fixture.
TypeError: __init__() got an unexpected keyword argument 'meta'
CharmSpec constructor changed; 'meta' is no longer a keyword argument (use positional or other keys).
fixUse CharmSpec(MyCharm, meta={...}) is correct; if error persists, check version >=7.0 and use: CharmSpec(MyCharm, meta={...}) still works. This error may be from mixing versions. Upgrade
Version history
8.7.1latest on PyPI · released May 28, 2026
Audit
Dependencies
opsrequiredCore ops library; ops-scenario is part of the same project.
pyyamloptionalUsed for YAML handling in charm metadata and actions.
pytestoptionalRecommended test runner; not strictly required but commonly used.