suite.register

register_suite() — class decorator that registers an OttoSuite subclass as a Typer subcommand on suite_app.

Registration happens at class-definition time (import time). cli/test.py reads _SUITE_REGISTRY after configmodule has finished loading (which is also when this module is first imported via test-file auto-scan) and adds the pre-built sub-Typers to suite_app.

No circular imports: this module never imports from otto.cli.test at module level. The runner function uses a lazy import so the actual test execution can reach run_suite only when the CLI command is invoked, by which time cli/test.py is fully loaded.

class otto.suite.register.OttoOptionsPlugin(options)

Bases: object

Pytest plugin that provides the suite Options instance as a fixture.

Tests request the suite_options fixture as a parameter:

async def test_something(self, suite_options) -> None:
    assert suite_options.device_type == "router"
suite_options()

The Options dataclass instance populated from CLI arguments.

Return type:

Any

otto.suite.register.register_suite(*args, **kwargs)

Class decorator that registers an OttoSuite subclass as a suite_app subcommand.

Usage:

@register_suite()
class TestMyDevice(OttoSuite):
    """Run device validation tests."""

    @dataclass
    class Options(RepoOptions):
        firmware: str = "latest"
        check_interfaces: bool = True

    async def test_something(self, suite_options):
        opts = suite_options  # fully-typed Options instance
        ...

The decorated class is returned unchanged. The decorator only has a side-effect: it builds a Typer sub-app from the class’s Options inner class (if present) and appends it to _SUITE_REGISTRY. cli/test.py reads the registry at module load time and adds the sub-apps to suite_app.