Overview
Pyrig uses autouse fixtures to automatically validate project structure, enforce test coverage, and maintain code quality. These fixtures run automatically before and/or after every test session without requiring explicit imports.What are Autouse Fixtures?
Autouse fixtures are pytest fixtures withautouse=True that run automatically:
pytest.
Session-Scoped Fixtures
All autouse fixtures run at session scope (once per test session) to validate project-wide concerns.Available Autouse Fixtures
assert_no_unstaged_changes
Purpose: Verify no unstaged git changes before and after tests (CI only) When: Before and after test session Scope: CI environments only (GitHub Actions) What it checks:- No unstaged changes before tests run
- No unstaged changes after tests complete
assert_root_is_correct
Purpose: Verify project root structure and configuration files When: Before test session What it checks:- All ConfigFile subclasses are correct
- Configuration files exist and are valid
- Creates missing configuration files
- Updates incorrect configuration files
assert_no_namespace_packages
Purpose: Ensure all packages have__init__.py files
When: Before test session
What it checks:
- Every directory with Python files has an
__init__.py
- Creates missing
__init__.pyfiles
assert_all_src_code_in_one_package
Purpose: Enforce single source package with specific structure When: Before test session What it checks:- Only expected top-level packages exist (source package and
tests) - Source package has exactly
rig,src,resourcessubpackages - Source package has exactly
mainmodule
assert_src_package_correctly_named
Purpose: Verify source package naming conventions When: Before test session What it checks:- Current directory name matches
pyproject.tomlproject name - Source package name matches project name (kebab-case → snake_case)
assert_all_modules_tested
Purpose: Ensure every source module has a corresponding test module When: Before test session What it checks:- Every source module has a test module
- Every function has a test function
- Every class has a test class
- Every method has a test method
- Generates test skeletons for missing tests
- Creates test modules for untested source modules
- Non-destructive: preserves existing tests
assert_dependencies_are_up_to_date
Purpose: Verify dependencies are current viauv lock --upgrade and uv sync
When: Before test session
What it checks:
- Dependencies are up to date
- Dependencies are installed
- Runs
uv lock --upgrade - Runs
uv sync
assert_src_runs_without_dev_deps
Purpose: Verify source code doesn’t depend on dev dependencies When: Before test session What it checks:- Source code can run without dev dependencies
- All source modules can be imported
- CLI entry point works
- Creates temporary environment
- Installs project without dev dependencies
- Imports all source modules
- Runs CLI with
--help
assert_src_does_not_use_rig
Purpose: Enforce separation between source code and rig code When: Before test session What it checks:- Source code (
src/) doesn’t import rig code (rig/)
assert_project_mgt_is_up_to_date
Purpose: Verifyuv is up to date
When: Before test session
What it checks:
uvpackage manager is current
- Runs
uv self update
- No internet connection
- Running in CI (GitHub Actions)
- Rate limit exceeded (GitHub API)
Auto-Fix Behavior
Many autouse fixtures auto-fix issues and then fail:- Detect issue - Fixture identifies a problem
- Auto-fix - Fixture attempts to fix the problem
- Fail - Fixture fails with a message listing what was fixed
- Developer review - You review and commit the changes
- Re-run tests - Tests pass on next run
- Issues are fixed automatically
- You’re aware of what changed
- Changes are committed to version control
Disabling Autouse Fixtures
Disable Specific Fixtures
You can disable specific autouse fixtures using pytest’s--deselect option:
Conditional Execution
Some fixtures already have conditional execution:- CI-only:
assert_no_unstaged_changes - Internet required:
assert_dependencies_are_up_to_date,assert_src_runs_without_dev_deps,assert_project_mgt_is_up_to_date - Local-only:
assert_project_mgt_is_up_to_date(skips in CI)
Creating Custom Autouse Fixtures
Create your own autouse fixtures in your project’stests/ directory:
- Use
scope="session"for project-wide validation - Add clear error messages
- Auto-fix when possible
- Document what the fixture checks
Fixture Discovery
Autouse fixtures are discovered from:- pyrig’s fixtures -
pyrig.rig.tests.fixtures.autouse - Dependent package fixtures - Equivalent
fixtures.autousemodules - Project fixtures - Your project’s
tests/directory
pytest_plugins in tests/conftest.py.
Understanding Fixture Output
Success
When all autouse fixtures pass, pytest shows:Failure
When an autouse fixture fails, pytest shows:Best Practices
1. Review Auto-Fixed Changes
When a fixture auto-fixes an issue:2. Understand Fixture Purpose
Read the fixture docstring to understand what it checks:3. Fix Root Causes
Don’t just delete auto-generated files - fix the root cause:4. Use in CI
Autouse fixtures are perfect for CI validation:- No unstaged changes during tests
- All modules are tested
- Dependencies are current
- Source doesn’t depend on dev dependencies
Fixture Locations
Pyrig’s autouse fixtures are located in:pyrig/rig/tests/fixtures/autouse/session.py:1
Next Steps
Test Structure
Learn about test organization
Best Practices
Testing best practices and patterns