Follow-up to feedback from @m13v on #111. Building out the test-state primitive discussed there.
Problem
Persona-driven tests create persistent state — user accounts, OAuth grants, throwaway emails, SMS numbers, API tokens. A crashed test run leaves orphans that block the next run. Inline try/finally teardown works for the happy path but not for SIGKILL, OOM, or a developer hitting Ctrl-C mid-test.
Design: PersonaFixture
A primitive that owns all credentials for a persona across a test run and guarantees cleanup even after abrupt termination.
async with PersonaFixture("novice_sarah") as persona:
email = await persona.disposable_email()
phone = await persona.sms_number()
token = await persona.oauth_grant("github")
# ...test runs...
# On exit (success or abort), all resources reaped
Cleanup registry
Per-persona cleanup tasks are persisted to disk (e.g. .taos/test-fixtures/{run_id}.json) as they're created, not just kept in memory:
- Start of test creates entry in registry
- Each resource acquisition appends to the entry
- Clean exit deletes the entry
- A crashed process leaves the entry behind
- Next test run's fixture startup sweeps orphaned entries older than N minutes and runs their cleanup
Makes cleanup genuinely idempotent: replaying a cleanup that's already run is a no-op.
Resource backends
| Resource |
Backend |
Cleanup |
| Disposable email |
mail.tm or mailsac API |
Delete mailbox |
| SMS number |
sms-activate / twilio test numbers |
Release number |
| OAuth grant |
provider-specific test accounts |
Revoke token |
| User account |
API DELETE on test backend |
Drop user row |
Each backend implements a uniform acquire() / release(token) interface so the fixture doesn't know about provider specifics.
Acceptance
Follow-up to feedback from @m13v on #111. Building out the test-state primitive discussed there.
Problem
Persona-driven tests create persistent state — user accounts, OAuth grants, throwaway emails, SMS numbers, API tokens. A crashed test run leaves orphans that block the next run. Inline try/finally teardown works for the happy path but not for SIGKILL, OOM, or a developer hitting Ctrl-C mid-test.
Design: PersonaFixture
A primitive that owns all credentials for a persona across a test run and guarantees cleanup even after abrupt termination.
Cleanup registry
Per-persona cleanup tasks are persisted to disk (e.g.
.taos/test-fixtures/{run_id}.json) as they're created, not just kept in memory:Makes cleanup genuinely idempotent: replaying a cleanup that's already run is a no-op.
Resource backends
Each backend implements a uniform
acquire() / release(token)interface so the fixture doesn't know about provider specifics.Acceptance
PersonaFixturecontext manager exists in test infra