Total Tests: 9
Status: ✅ All passing
What it tests: UV_RUN_ACTIVE prevents infinite re-execution
Why critical: Without this, auto-uv would re-execute itself forever
How it works:
- Creates a script that counts executions
- Verifies execution count stays low (no loop)
- Has 5-second timeout to catch runaway loops
Prevents:
# BAD: Without UV_RUN_ACTIVE check
python script.py
→ uv run script.py
→ uv run uv run script.py
→ uv run uv run uv run script.py
→ ∞ INFINITE LOOPWhat it tests: No sys.exit() during site initialization
Why critical: sys.exit() during import crashes Python
Regression: v0.1.1 bug - "Fatal Python error: init_import_site"
Prevents:
# BAD: v0.1.1 code
def auto_use_uv():
result = subprocess.run(["uv", "run"] + sys.argv)
sys.exit(result.returncode) # ← CRASHES during import!Fixed in v0.1.2:
# GOOD: v0.1.2 code
def auto_use_uv():
if __main__.__file__ != sys.argv[0]: # ← Check if we're in main
return # Don't intercept during import
os.execve(uv_path, cmd, os.environ) # ← Replace process, don't exitWhat it tests: main.file check prevents import interception
Why critical: Intercepting during import causes crashes
How it works:
- Imports auto_uv module
- Verifies no interception happens
- Checks import completes successfully
Prevents:
# BAD: Intercepting during import
import auto_uv # ← This should NOT trigger re-executionWhat it tests: Scripts in site-packages are NOT intercepted
Why critical: Intercepting dbt, pip, pytest causes crashes
Regression: v0.1.0 bug - dbt debug crashed
Prevents:
# BAD: v0.1.0 behavior
$ dbt debug
Fatal Python error: init_import_site: Failed to import the site moduleWhat it tests: Relative vs absolute path comparison works
Why critical: Prevents incorrect interception decisions
How it works:
- Tests with relative path (./script.py)
- Tests with absolute path (/full/path/script.py)
- Verifies both are normalized before comparison
Prevents:
# BAD: Without normalization
__main__.__file__ = "script.py" # relative
sys.argv[0] = "/full/path/script.py" # absolute
# These don't match! → Incorrect interceptionWhat it tests: Detects pyproject.toml, .venv, uv.lock
Coverage:
- Directory with pyproject.toml
- Directory with .venv
- Directory with uv.lock
- Directory with no markers (should return False)
- Subdirectory of project (walks up tree)
What it tests: Decision logic for when to intercept
Coverage:
- UV_RUN_ACTIVE=1 → don't intercept
- AUTO_UV_DISABLE=1 → don't intercept
- uv available → intercept
- uv not available → don't intercept
What it tests: Basic script execution works
Coverage:
- Script runs successfully
- Returns correct exit code
- Output is captured correctly
What it tests: AUTO_UV_DISABLE=1 works
Coverage:
- Script runs without UV_RUN_ACTIVE when disabled
- Environment variable is respected
✅ Empty sys.argv[0]
✅ No main.file (frozen executables)
✅ Relative vs absolute paths
✅ Site-packages exclusion
✅ dist-packages exclusion
✅ bin/ directory exclusion
✅ Scripts/ directory exclusion
✅ sys.prefix exclusion
✅ sys.base_prefix exclusion
✅ System directories (/usr/bin, etc.)
✅ Project detection (pyproject.toml, .venv, uv.lock)
✅ Parent directory search (up to 10 levels)
✅ UV_RUN_ACTIVE loop prevention
✅ AUTO_UV_DISABLE flag
✅ Import-time safety
- Scripts\ vs Scripts/ separator
- uv.exe vs uv.cmd vs uv.bat detection
- Windows system directories (C:\Windows\System32)
- Symlinks to scripts
- Symlinks in project detection
- uv executable not executable
- Script file not readable
- Script deleted between check and exec
- Project markers changed during execution
- python -m pytest
- python -m pip
- User modules vs installed modules
# Run all tests
make test
# Run with verbose output
AUTO_UV_DISABLE=1 PYTHONPATH=src uv run pytest tests/ -v
# Run specific test
AUTO_UV_DISABLE=1 PYTHONPATH=src uv run pytest tests/test_auto_uv.py::test_no_infinite_loop -v
# Run with coverage
AUTO_UV_DISABLE=1 uv run pytest tests/ --cov=auto_uv --cov-report=term-missing- Regression tests - Every bug gets a test
- Edge case coverage - Test boundary conditions
- Integration tests - Test end-to-end behavior
- Unit tests - Test individual functions
- Safety first - Test that we don't break things
When adding a test:
- Name it descriptively:
test_<feature>_<scenario> - Add docstring: Explain what and why
- Use Arrange-Act-Assert: Clear structure
- Clean up: Use context managers
- Add to main: Include in manual test runner