Principle:Microsoft Playwright Clean Up Test Resources
| Knowledge Sources | |
|---|---|
| Domains | API_Testing, HTTP, Test_Teardown |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Cleaning up test-created resources and disposing of HTTP client contexts after tests complete prevents resource leaks, data pollution, and ensures test isolation across runs.
Description
The cleanup phase is the mirror of the setup phase: where setup creates resources and establishes state, cleanup removes those resources and releases allocated connections. Neglecting cleanup leads to several problems:
Why Cleanup Matters
- Data pollution: Test-created records accumulate in the database, potentially causing subsequent test runs to fail due to duplicate key violations, unexpected query results, or exceeded quotas.
- Resource leaks: HTTP client contexts hold open connections, socket handles, and in-memory response buffers. Failing to dispose of these leads to memory leaks and eventually connection exhaustion.
- Test interference: When tests leave behind state, later tests may encounter unexpected preconditions, making failures non-deterministic and difficult to debug.
- Environment cleanliness: Shared test environments (staging servers, CI pipelines) become cluttered with stale test data if cleanup is not performed.
Types of Cleanup
- Resource deletion: Sending HTTP DELETE requests to remove entities created during setup (users, articles, orders, etc.).
- State reversal: Undoing configuration changes made during the test (resetting feature flags, revoking permissions).
- Context disposal: Closing the HTTP client context to release network connections, flush tracing data, and clear cached response bodies.
- Global teardown: Project-level cleanup that runs once after all test suites complete, suitable for removing shared test infrastructure.
Cleanup Guarantees
A well-designed cleanup mechanism must execute even when tests fail. The afterAll or afterEach hooks in test frameworks are specifically designed for this: they run regardless of whether the preceding tests passed or failed, ensuring cleanup is never skipped.
Usage
Apply this principle whenever:
- Tests create resources on a shared server that must be removed after testing.
- HTTP client contexts are created manually (outside of automatic fixture management).
- You need to ensure that test environments remain clean between runs.
- Tests modify server-side state (configurations, permissions) that must be restored.
- You are running tests in CI/CD pipelines where accumulated test data would affect reliability.
Theoretical Basis
Cleanup follows the Teardown phase that complements the Arrange-Act-Assert pattern:
// SETUP: Create test resources
beforeAll(async ({ request }) => {
response = await request.post("/api/users", {
data: { username: "testuser", role: "admin" }
})
createdUserId = (await response.json()).id
})
// TESTS: Execute against the prepared state
test("verify user exists", async ({ request }) => {
response = await request.get("/api/users/" + createdUserId)
assert(response.ok())
})
// TEARDOWN: Clean up resources and dispose context
afterAll(async ({ request }) => {
// Delete the test-created resource
await request.delete("/api/users/" + createdUserId)
// Dispose the HTTP client context
await request.dispose()
})
Design principles for cleanup:
- Reverse order: Resources should be deleted in the reverse order of creation to respect dependency constraints (e.g., delete child records before parent records).
- Idempotent deletion: Cleanup should tolerate resources that were already deleted (e.g., by a test that explicitly deletes them), typically by ignoring 404 responses.
- Guaranteed execution: Using
afterAll/afterEachhooks ortry/finallyblocks to ensure cleanup runs even after test failures. - Automatic disposal: Modern frameworks support
Symbol.asyncDisposeor similar protocols for automatic resource cleanup when the context goes out of scope.