Fixture Sharing System
pyrig provides a fully inheritable pytest fixture library that every project
built on pyrig gets automatically. Any fixture defined anywhere in the
rig/tests/fixtures/ package tree of pyrig — or in any installed package that
depends on pyrig — is available in every test module of every downstream project
without explicit imports, plugin declarations, or conftest.py wiring.
How Fixtures Are Discovered
The mechanism is driven by a single conftest.py at pyrig.rig.tests.conftest.
Which is registered as a pytest plugin in your generated conftest.py and
thus executed on every test run. When pytest starts, it executes this file, which:
- Finds all installed packages that depend on pyrig, including the current project itself
- For each package in that chain, locates the equivalent of the
rig.tests.fixturespackage (e.g.myproject.rig.tests.fixtures). - Recursively collects every
.pyfile in that package, skipping__init__.pyfiles. - Converts each path to a dotted module name and adds it to
pytest_plugins.
pytest treats every module in pytest_plugins as a plugin, which means all
fixtures defined in those modules become globally available. The effect is that
the fixture namespace of any pyrig-based project is the union of fixtures
contributed by every package in its dependency chain.
This can be very useful if you have a base package and want other projects
to share some common fixtures for their test suites.
Where to Define Fixtures
The fixtures package is organised by purpose. Any .py file placed anywhere
inside <package>/rig/tests/fixtures/ (at any depth) is picked up automatically.
pyrig itself ships two fixture modules:
fixtures.py— general-purpose shared fixtures used across the whole ecosystem.autouse/session.py— session-scoped autouse fixtures that enforce project health on every test run.
Downstream projects follow the same structure. A project can add fixtures either at the top level of its fixtures package or in subdirectories for example, grouping fixtures by topics.
Adding Fixtures to a Project
Defining a new fixture is as simple as writing a @pytest.fixture-decorated
function in any .py file under <package>/rig/tests/fixtures/. No
registration in a conftest.py is required. The fixture is available
project-wide on the next test run.
You can also generate a new fixture skeleton with the mkfixture command:
uv run pyrig mkfixture my-fixture-name
This will create a new file src/my_project/rig/tests/fixtures/fixtures.py and
add a new fixture function skeleton named my_fixture_name to it with a
@pytest.fixture decorator. If the file already exists, the new fixture will be
added to it without affecting any existing content.
Autouse Fixtures
pyrig defines a few autouse fixtures in autouse/session.py. These are automatically
on every test run without being requested by any test. They act as continuous
project health checks, turning a passing test suite into a guarantee that the
project is structurally sound.
all_modules_tested— checks that every source module has a fully mirrored test module.all_config_files_correct— checks that all version-controlled config files match their expected content.no_namespace_packages— all package directories have an__init__.py.no_unstaged_changes_in_ci— no unstaged file changes exist before or after the session when running in CI.no_dev_deps_in_source_code— source code can be imported and the CLI can run in an isolated environment that has no dev dependencies installed.