Test Suite Repair Pattern
When an audit or CI identifies failing tests, follow this pattern to fix them efficiently without introducing regressions.
When to Use
- Test suite has 1-10 failing tests
- Audit reports test failures (e.g., Tier-1 repo audit identifying 6 failing tests)
- CI pipeline is broken and needs fixing
- Tests have stale expectations after code changes
Phase 1: Triage
- Run the full test suite to get the exact failure list:
cd <repo>
uv run python -m pytest tests/ --noconftest -v 2>&1 | grep FAILED
- Run each failing test individually to get the full traceback:
uv run python -m pytest tests/path/to/test.py::TestClass::test_name -v 2>&1 | tail -30
- Categorize failures:
- Path/fixture issues: Tests create temp dirs but code uses CWD
- Stale assertions: Test expects behavior that was never implemented
- Missing methods: Test calls method that doesn't exist
- Wrong imports: Test references nonexistent module/class
- Real bugs: Actual code defect
Phase 2: Root Cause Analysis
For each failure, trace the code path:
- Read the failing test (what it expects)
- Read the code path it exercises (what it actually does)
- Identify the mismatch
Common patterns found:
agents_base_dir ignored: Test passes dir in args dict, but __init__ initializes components with CWD before execute() can override. Fix: pass base_dir=Path(tmpdir) to constructor, not in dict.
- Stale YAML fields: Code writes field
integration: True but dataclass expects enabled: True. Fix both writer and reader.
- Missing method: Test calls
command.validate_repository() — method doesn't exist. Fix: replace with actual integration test or implement stub.
- Wrong import path: Test imports from
cli.manager but class is in commands.cli. Fix import.
Phase 3: Fix
Apply targeted patches:
- For path/fixture issues: Pass correct
base_dir or Path(tmpdir) to constructor
- For stale assertions: Update assertion to match actual implemented behavior, or add
# TODO comment for unimplemented feature
- For missing methods: Either implement the method OR rewrite the test to use existing API
- For wrong imports: Fix the import path
Critical rules:
- NEVER change production code to match a broken test — the test is wrong, not the code (unless you've verified it's a real bug)
- If a feature isn't implemented, adjust the test expectation, don't implement the feature
- When fixing assertions, verify the agent structure/config actually exists rather than checking specific field values
Phase 4: Verification
- Run the specific test file to confirm all its tests pass:
uv run python -m pytest tests/path/to/test_file.py -v 2>&1 | tail -10
- Run the FULL test suite to verify no regressions:
uv run python -m pytest tests/ --noconftest -q 2>&1 | tail -5
- Expected: All pass, 0 failed. Accept: 0 failed (skipped is fine).
Phase 5: Clean Commit
- Clean up test artifacts before committing:
# Revert timestamp drifts in test result YAML files
git checkout -- tests/modules/*/results/*.yml
git checkout -- tests/modules/*/results/*.html
git checkout -- tests/modules/**/input_data/*.xlsx
# Remove test-generated directories
rm -rf agents/
git checkout -- agents/ # if tracked
# Verify only real code/test changes remain
git status --short
- Commit with descriptive message:
git commit -m "fix(tests): resolve <N> failing tests — <total> passed 0 failed (#issue)
- test_name1: root cause + fix
- test_name2: root cause + fix"
- Push and verify CI.
Pitfalls
- patch tool mangles files with \r\n line endings — use python3 terminal to edit:
with open(path, 'r') as f: content = f.read()
content = content.replace(old, new, 1)
with open(path, 'w') as f: f.write(content)
- Test artifacts in git tree — running tests creates
agents/ dir and modifies result YAML timestamps. Always git checkout these before committing.
- Staged accidentally —
git add -A will include test artifacts. Stage specific files instead: git add tests/agent_os/commands/...
- Fixing the wrong layer — if test passes
agents_base_dir in execute() dict but components are initialized in __init__, setting it in execute() is too late. Pass to constructor instead.
- Assuming feature exists — many tests assert behavior for unimplemented features (config_file loading, custom_structure, type auto-fallback). Adjust assertions, don't implement the feature.
Example: assetutilities 6-test fix (#1962)
Initial state: 6 failed, 1234 passed
- 5 tests used
agents_base_dir dict arg → fix: pass base_dir=Path(self.temp_dir) to constructor
- 1 test called nonexistent
validate_repository() → fix: rewrite as execute() integration test
- 2 tests had stale assertions for unimplemented features → fix: adjust expectation to match reality
Final state: 1235 passed, 9 skipped, 0 failed
1---2name: test-suit-repair-pattern3description: Systematically fix failing tests in a test suite — root cause analysis, targeted patches, regression verification, and documentation.4---56# Test Suite Repair Pattern78When an audit or CI identifies failing tests, follow this pattern to fix them efficiently without introducing regressions.910## When to Use1112- Test suite has 1-10 failing tests13- Audit reports test failures (e.g., Tier-1 repo audit identifying 6 failing tests)14- CI pipeline is broken and needs fixing15- Tests have stale expectations after code changes1617## Phase 1: Triage18191. Run the full test suite to get the exact failure list:20 ```bash21 cd <repo>22 uv run python -m pytest tests/ --noconftest -v 2>&1 | grep FAILED23 ```242. Run each failing test individually to get the full traceback:25 ```bash26 uv run python -m pytest tests/path/to/test.py::TestClass::test_name -v 2>&1 | tail -3027 ```283. Categorize failures:29 - **Path/fixture issues**: Tests create temp dirs but code uses CWD30 - **Stale assertions**: Test expects behavior that was never implemented31 - **Missing methods**: Test calls method that doesn't exist32 - **Wrong imports**: Test references nonexistent module/class33 - **Real bugs**: Actual code defect3435## Phase 2: Root Cause Analysis3637For each failure, trace the code path:381. Read the failing test (what it expects)392. Read the code path it exercises (what it actually does)403. Identify the mismatch4142Common patterns found:43- **`agents_base_dir` ignored**: Test passes dir in args dict, but `__init__` initializes components with CWD before `execute()` can override. Fix: pass `base_dir=Path(tmpdir)` to constructor, not in dict.44- **Stale YAML fields**: Code writes field `integration: True` but dataclass expects `enabled: True`. Fix both writer and reader.45- **Missing method**: Test calls `command.validate_repository()` — method doesn't exist. Fix: replace with actual integration test or implement stub.46- **Wrong import path**: Test imports from `cli.manager` but class is in `commands.cli`. Fix import.4748## Phase 3: Fix4950Apply targeted patches:511. **For path/fixture issues**: Pass correct `base_dir` or `Path(tmpdir)` to constructor522. **For stale assertions**: Update assertion to match actual implemented behavior, or add `# TODO` comment for unimplemented feature533. **For missing methods**: Either implement the method OR rewrite the test to use existing API544. **For wrong imports**: Fix the import path5556Critical rules:57- NEVER change production code to match a broken test — the test is wrong, not the code (unless you've verified it's a real bug)58- If a feature isn't implemented, adjust the test expectation, don't implement the feature59- When fixing assertions, verify the agent structure/config actually exists rather than checking specific field values6061## Phase 4: Verification62631. Run the specific test file to confirm all its tests pass:64 ```bash65 uv run python -m pytest tests/path/to/test_file.py -v 2>&1 | tail -1066 ```672. Run the FULL test suite to verify no regressions:68 ```bash69 uv run python -m pytest tests/ --noconftest -q 2>&1 | tail -570 ```713. Expected: All pass, 0 failed. Accept: 0 failed (skipped is fine).7273## Phase 5: Clean Commit74751. Clean up test artifacts before committing:76 ```bash77 # Revert timestamp drifts in test result YAML files78 git checkout -- tests/modules/*/results/*.yml79 git checkout -- tests/modules/*/results/*.html80 git checkout -- tests/modules/**/input_data/*.xlsx81 82 # Remove test-generated directories83 rm -rf agents/84 git checkout -- agents/ # if tracked85 86 # Verify only real code/test changes remain87 git status --short88 ```892. Commit with descriptive message:90 ```bash91 git commit -m "fix(tests): resolve <N> failing tests — <total> passed 0 failed (#issue)92 93 - test_name1: root cause + fix94 - test_name2: root cause + fix"95 ```963. Push and verify CI.9798## Pitfalls991001. **patch tool mangles files with \r\n line endings** — use python3 terminal to edit:101 ```python102 with open(path, 'r') as f: content = f.read()103 content = content.replace(old, new, 1)104 with open(path, 'w') as f: f.write(content)105 ```1062. **Test artifacts in git tree** — running tests creates `agents/` dir and modifies result YAML timestamps. Always `git checkout` these before committing.1073. **Staged accidentally** — `git add -A` will include test artifacts. Stage specific files instead: `git add tests/agent_os/commands/...`1084. **Fixing the wrong layer** — if test passes `agents_base_dir` in execute() dict but components are initialized in `__init__`, setting it in execute() is too late. Pass to constructor instead.1095. **Assuming feature exists** — many tests assert behavior for unimplemented features (config_file loading, custom_structure, type auto-fallback). Adjust assertions, don't implement the feature.110111## Example: assetutilities 6-test fix (#1962)112113Initial state: 6 failed, 1234 passed114- 5 tests used `agents_base_dir` dict arg → fix: pass `base_dir=Path(self.temp_dir)` to constructor115- 1 test called nonexistent `validate_repository()` → fix: rewrite as execute() integration test116- 2 tests had stale assertions for unimplemented features → fix: adjust expectation to match reality117Final state: 1235 passed, 9 skipped, 0 failed