Use after implementation or refactoring, or during test-quality review, to tidy up tests left behind. Removes temporary or duplicate tests, restores `.only` or `.skip`, or cleans orphaned test resources; not for merely adding tests or running tests. Do not apply mechanically during implementation just because the work follows TDD; use only when the user asks for test-tidying or an explicit test-tidying phase begins.
73
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Work can produce tests that help diagnose a problem or reach Green but do not belong in the final result. This is unavoidable in agentic coding, where verification is a necessary part of the workflow. Do not try to prevent these tests from being created; tidy them up after the work.
During tidying, remove temporary tests and remove or merge duplicate tests. Do not expand the scope into general test quality improvements or a search for missing tests.
.only, .skip, retry, or timeout added temporarily during the current work to its original state.Do not use tidying as a reason to add tests or search for missing tests. Do not expand beyond removing temporary tests and removing or merging duplicate tests into general test quality improvements. Do not change product behavior, public interfaces, or agreed test boundaries.
A test that was needed to reach Green during the work but no longer protects a contract is a Throwaway Test. A test that protects a contract still requiring verification is a Regression Test. Do not remove a test merely because it was created during the work; distinguish between the two.
Handling principles
test("removes the Save button from the profile editing screen", () => {
render();
expect(screen.queryByRole("button", { name: "Save" })).not.toBeInTheDocument();
});test("user updates their profile bio", async ({ page }) => {
await page.goto("/profile");
await page.getByRole("button", { name: "Edit profile" }).click();
await page.getByLabel("Bio").fill("Updated bio");
// Temporary assertions that only confirm the change
expect(page.queryByRole("button", { name: "Save" })).not.toBeInTheDocument();
expect(page.queryByRole("button", { name: "Done" })).toBeVisible();
await page.getByRole("button", { name: "Done" }).click();
await expect(page.getByRole("status")).toHaveText("Profile saved");
await expect(page.getByText("Updated bio")).toBeVisible();
});lodash.sortBy and replace it with Array.prototype.toSorted. Keep the sorting result unchanged."// Existing test
test("returns products in ascending price order", () => {
const items = [{ price: 3 }, { price: 1 }];
expect(sortItems(items)).toEqual([{ price: 1 }, { price: 3 }]);
});
// New test
test("sortItems calls Array.prototype.toSorted", () => {
const toSorted = spyOn(Array.prototype, "toSorted");
sortItems([{ price: 3 }, { price: 1 }]);
expect(toSorted).toHaveBeenCalled();
});createProfileCache and adds a dedicated test.createProfileCache.test("profile cache loads the same user only once", async () => {
const loadProfile = vi.fn().mockResolvedValue(profile);
// The function is unused by production code but still exists, so the test passes
const cache = createProfileCache(loadProfile);
await cache.get("user-1");
await cache.get("user-1");
expect(loadProfile).toHaveBeenCalledTimes(1);
});internalNote contains sensitive information for support agents only. Do not expose it in customer API responses."test("does not expose internal support notes in customer responses", async () => {
const response = await getCustomer("customer-1");
expect(response.body).not.toHaveProperty("internalNote");
});internalNote is itself an information-disclosure contract that must remain protected in external responses, so this is a Regression Test.Do not treat tests as needless duplication merely because they verify some of the same behavior. A test is a Redundant Test when its contract, scenario, risk, and verification role fully overlap with another test, or when one role has been split across tests without reason. Identical test code is not the criterion.
Decision principles
// Existing test
test("authenticated user retrieves their own profile", async () => {
const response = await getProfile(authenticatedSession);
expect(response.status).toBe(200);
expect(response.body.id).toBe("user-1");
});
// New test
test("authenticated profile retrieval succeeds", async () => {
const response = await getProfile(authenticatedSession);
expect(response.status).toBe(200);
expect(response.body.id).toBe("user-1");
});test("checkout with a valid cart confirms the order", async () => {
const order = await checkout(validCart, validPaymentMethod);
expect(order.status).toBe("confirmed");
});
// A test that needlessly narrows verification of the same behavior
test("checkout with a valid cart returns an order ID", async () => {
const order = await checkout(validCart, validPaymentMethod);
// Assertion to merge into the test above
expect(order.id).toBe("order-1");
});// User Journey Test that verifies representative behavior
test("user purchases a product", async ({ page }) => {
await page.goto("/products/product-1");
await page.getByRole("button", { name: "Add to cart" }).click();
await page.getByRole("link", { name: "Cart" }).click();
await page.getByRole("button", { name: "Checkout" }).click();
await expect(page.getByRole("status")).toHaveText("Order complete");
});
// Focused Test that verifies a specific implementation
test("checkout with a valid cart confirms the order", async () => {
const order = await checkout(validCart, validPaymentMethod);
expect(order.id).toBe("order-1");
expect(order.status).toBe("confirmed");
});Residue is not a test itself. It consists of test execution settings changed temporarily during the work and test resources left unused after an implementation change or after tests are removed or merged.
.only, .skip, retry, and timeout settings added or changed during the current work to their original state. Do not change existing settings.Report the results of both investigations and modifications in a message. Write the report in the user's language. The report does not merely summarize actual changes; it records the outcome for every test, assertion, and piece of residue judged within the tidying scope. Report items that were kept and candidates requiring user confirmation, not only items that were removed or restored.
Classify each item as Transience, Overlap, or Residue according to the decision criteria. When one target leads to distinct decisions, such as removing a test and then removing its resources, report them as separate items.
Start with an overall summary, followed by each decision item. Items that share the same basis and classification may be grouped when doing so loses no information.
- Scope: (files and tests reviewed)
- Reviewed: (number of test cases, assertions, and resources)
- Results: (number removed, partially removed, merged, kept, restored, and requiring user confirmation)
- Verification: (commands run and results — modification reports only)
## 1. [Category] Brief description of the issue
- Target: `path:line` — test, assertion, or resource name
- Basis: (verified facts such as the current contract, its purpose during the work, and its relationship to other tests)
- Classification: (`Throwaway Test`, `Regression Test`, `Redundant Test`, `Complementary Test`, `Residue`, or a candidate in the relevant category)
- Recommendation: (remove, partially remove, merge, keep, restore, or defer based on the investigation — investigation reports only)
- Action: (removal, partial removal, merge, retention, restoration, or deferral actually performed — modification reports only)
- User confirmation: (missing evidence that prevented a decision and the question for the user — include only when the decision is deferred)Test tidying is complete. Decisions and actions:
- Scope: `tests/profile.spec.ts`, `tests/checkout.spec.ts`, `tests/export.spec.ts`
- Reviewed: 6 test cases, 2 individual assertions, 2 resources
- Results: 1 test removed, 2 assertions removed, 4 tests kept, 2 resources removed, 1 item requires user confirmation
- Verification: `pnpm test -- tests/profile.spec.ts tests/checkout.spec.ts tests/export.spec.ts` — 24 tests passed
## 1. [Transience] Assertions that only confirm the profile button text change
- Target: `tests/profile.spec.ts:42` — `user updates their profile bio`
- Basis: The profile-saving result remains a contract to protect, but the two assertions checking the previous and current Save button text only confirm completion of this text change.
- Classification: The test case is a `Regression Test`; each of the two assertions is a `Throwaway Test`
- Action: Kept the test case and removed only the two assertions
## 2. [Overlap] New test that duplicates an existing profile retrieval test
- Target: `tests/profile.spec.ts:78`, `tests/profile.spec.ts:91` — 2 tests for an authenticated user's profile retrieval
- Basis: Both tests use the same seam to verify the same precondition, action, and result, and the existing test fully replaces the new test's contract, scenario, risk, and verification role.
- Classification: The new test is a `Redundant Test`
- Action: Removed the new test and kept the existing test
## 3. [Overlap] Overlapping verification in checkout tests with different roles
- Target: `tests/checkout.spec.ts:12`, `tests/checkout.spec.ts:67` — product-purchase User Journey Test and checkout Focused Test
- Basis: Successful checkout overlaps, but one test protects the representative journey and connections between components while the other protects checkout's narrow contract.
- Classification: Each test is a `Complementary Test`
- Action: Kept both tests
## 4. [Transience] Test whose ongoing contract for the previous CSV format is unclear
- Target: `tests/export.spec.ts:105` — `exports a profile in the previous CSV format`
- Basis: The current code alone does not establish whether the previous CSV format remains a supported contract or was retained only for comparison during the work.
- Classification: `Transience` candidate
- Action: Deferred the decision and kept the test
- User confirmation: There is no user instruction or specification establishing whether the previous CSV format remains supported. Should this format continue to be supported?
## 5. [Residue] Fixture and import left after removing a duplicate test
- Target: `tests/fixtures/profile.ts:18`, `tests/profile.spec.ts:4` — fixture and import used only by the removed profile retrieval test
- Basis: Nothing references them after the `Redundant Test` is removed.
- Classification: `Residue`
- Action: Removed the fixture and importSkip verification and use Recommendation instead of Action for each item.
I reviewed the tests in scope. Decisions and recommendations:
- Scope: `tests/profile.spec.ts`, `tests/checkout.spec.ts`, `tests/export.spec.ts`
- Reviewed: 6 test cases, 2 individual assertions, 2 resources
- Results: 1 test recommended for removal, 2 assertions recommended for removal, 4 tests recommended for retention, 2 resources recommended for removal, 1 item requires user confirmation
## 1. [Transience] Assertions that only confirm the profile button text change
- Target: `tests/profile.spec.ts:42` — `user updates their profile bio`
- Basis: The profile-saving result remains a contract to protect, but the two assertions checking the previous and current Save button text only confirm completion of this text change.
- Classification: The test case is a `Regression Test`; each of the two assertions is a `Throwaway Test`
- Recommendation: Keep the test case and remove only the two assertions
...omitted62ef4cc
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.