## TL;DR

A test that skips its teardown when it fails leaves the database dirty for everything after it. Resetting the database inside the victim test hides the gap but the dirty data keeps flowing to every other test. Find the test whose teardown didn't run and make its cleanup unconditional.

## The query

```text
my agent added a database reset to the failing test instead of finding the test that skipped its teardown on failure
```

## Steps

### 1. Confirm the victim is a dirty-database victim

Run the victim against a freshly migrated database. If it passes there and fails in the suite, the database state left by earlier tests is the problem, not the victim's logic.

Expected: green on a fresh database, red in suite context. The database is the shared state.

### 2. Find the test whose teardown was skipped

Look at the tests that ran before the victim in the failing run. Find any that failed or errored: a test that errors mid-way often skips the cleanup code that would have run on the success path. Check whether its teardown actually executed (add logging if you have to).

Expected: one earlier test that errored and left its rows behind. That is the gap.

### 3. Make the teardown unconditional

Move the cleanup so it runs whether the test passes or fails: fixture finalizers, try/finally blocks, or transactional tests that roll back instead of committing. The rule is simple: a test must leave the database as it found it, especially when it fails.

Expected: after the previously-failing test errors, the database is still clean. Verify by inspecting row counts between tests.

### 4. Remove the victim-side reset and re-run

Take the agent's database reset out of the victim. Run the suite: the victim should pass on its own merits now that the database arrives clean.

Expected: green suite with the victim in its original form. No test needs defensive resets.

## Use this when

- An agent added a truncate, delete-all, or re-migrate step to the failing test's setup
- The victim passes on a fresh database but fails after the suite runs
- An earlier test in the failing run errored (its teardown likely never ran)
- The "fix" made the victim robust to dirty data instead of keeping the data clean

## Not for this skill when

- The database is dirty because of a CI setup or migration problem (then no test's teardown is at fault)
- The victim fails on a fresh database too (the bug is in the victim or the code under test)
- The earlier test's teardown ran fine and the data is still wrong (the seed data or fixtures are wrong, not the teardown)
- Tests intentionally share database state by design (then the contract needs documenting, not teardown)

## Variant phrasings

### agent added a delete-all to the test's setup "to be safe"

"To be safe" is the tell. If every test needs it, one test is leaving the mess.

### the suite is green but each test now starts with a full reset

Suite-wide defensive resets are a tax on every run and they hide which test is dirty. Find the dirty one.

### a test that errors leaves rows behind, and the next test fails on unique constraints

Unique-constraint failures in the victim are the classic fingerprint of an earlier test's skipped teardown.

## Why it happens

The agent debugs the failing test, sees dirty data, and fixes what it can see: the victim's setup. It never investigates the earlier test because that test's failure looks like a separate, already-known issue ("oh, that one errors, we know about it"). But a test that errors AND skips teardown does double damage: its own failure plus poisoned state for everything downstream. The agent treats those as two unrelated problems because it never connects the error to the missing cleanup.

## Edge cases

- The teardown exists but is in the wrong scope: a function-scoped cleanup can't clean up session-scoped data. Match the teardown scope to the state scope.
- Transactional tests that commit on purpose: some tests need to commit. Those need explicit cleanup, not just rollback, and it must be unconditional.
- The earlier test errors in its own setup, before teardown is even registered: register cleanup as early as possible, or use a fixture that owns the data lifecycle.
- The database is shared across parallel workers: one worker's skipped teardown poisons another worker's tests. Either isolate databases per worker or make every teardown bulletproof.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst__DXUi8nDFNxgFznDvXbO3A
