suite.plugin¶
OttoPlugin — internal pytest plugin registered when otto invokes pytest.main().
Provides the pytest_runtest_makereport hook that attaches the per-phase
test report to each item (as item.rep_setup, item.rep_call,
item.rep_teardown). This makes pass/fail status available to fixtures
(including OttoSuite._test_lifecycle) during the teardown phase.
When sut_test_dirs is supplied, the pytest_ignore_collect hook
restricts collection to only those directories and their descendants,
ensuring that only tests defined in OTTO_SUT_DIRS repos are run.
Additional hooks:
pytest_runtest_protocolImplements stability testing (
--iterations/--duration). Repeats each test item within a single setup/teardown cycle, stopping when the iteration or time limit is reached.pytest_runtest_callImplements
@pytest.mark.retry(n)— retries the test body up to n times on failure, stopping on the first success.pytest_runtest_logreportIn stability mode, accumulates per-test pass/fail counts into the
StabilityCollectorattached to the plugin instance.
-
otto.suite.plugin.otto_cov_key : StashKey[bool] =
<_pytest.stash.StashKey object>¶ Stash key indicating that
--covwas passed tootto test. Fixtures can read this to decide whether to preserve.gcdafiles on remote hosts for post-run collection.
- class otto.suite.plugin.StabilityCollector¶
Bases:
objectAccumulates per-test pass/fail counts across multiple stability runs.
-
class otto.suite.plugin.OttoPlugin(sut_test_dirs=
None, stability_collector=None, cov=False, iterations=0, duration=0, monitor=False, monitor_interval=5.0, monitor_output=None, monitor_hosts=None)¶ Bases:
objectInternal pytest plugin used by
otto testto instrument test runs.Parameters¶
- sut_test_dirs :
Resolved test directories from all configured
OTTO_SUT_DIRSrepos (i.e. the union ofRepo.testsfor every repo). When provided, collection is restricted to these directories. Pass an empty list or omit to disable filtering.- stability_collector :
When running in stability mode, pass a
StabilityCollectorinstance here to accumulate pass/fail counts across repeated runs.
- pytest_configure(config)¶
Register the shared async timeout fixture and enforce auto asyncio mode.
OttoSuites always run with
asyncio_mode=autoso that async fixtures and test methods work without explicit@pytest.mark.asynciomarkers. This is distinct from otto’s own unit tests which useasyncio_mode=strict(set inpyproject.toml).- Return type:¶
None
- pytest_ignore_collect(collection_path, config)¶
Ignore any path not under a configured SUT test directory.
Returns
True(ignore) for paths outside all SUT test dirs. ReturnsNone(collect normally) for paths inside a SUT test dir or for ancestor directories that need to be traversed to reach one. When no SUT test dirs are configured, all paths are collected normally.- Return type:¶
bool|None
- pytest_runtest_protocol(item, nextitem)¶
Repeat each test item when stability mode is active.
When
--iterationsor--duration(or both) are specified, each collected test is executed multiple times within a single pytest session. Class-scoped fixtures (setup_class/teardown_class) remain cached by pytest for the lifetime of the class and fire only once. Method-scoped fixtures fire on every iteration.Unlike calling
runtestprotocolin a loop (which tears down all fixtures including class-scoped ones after each call), this hook runs setup once, repeats the call phase N times, then runs teardown once. This keeps class-scoped resources (SSH connections, deployed artifacts, etc.) alive across iterations.Returns
Trueto signal that this hook handled the item, orNoneto fall through to default behaviour.- Return type:¶
bool|None
- pytest_runtest_call(item)¶
Implement
@pytest.mark.retry(n)— retry the test body up to n times.Stops on the first success. Re-raises the last exception if all attempts fail. Each failed attempt is logged at WARNING level.
- Return type:¶
None
- pytest_report_teststatus(report, config)¶
Suppress pytest’s per-test progress characters.
otto’s RichHandler streams log output to the console in real time, so pytest’s dot/
F/Ecolumn adds no information and races with log records when capture is disabled. Returning an empty short-letter keeps the category and verbose word intact (so failure summaries and the final pass/fail counts still render) while stopping the terminal reporter from writing anything per test.- Return type:¶
tuple[str,str,str] |None