Refactor a Test Suite for DRY Using AI
Scans a set of test files and identifies duplicated setup, fixture state, and assertion patterns — proposes refactors using Playwright fixtures, factory functions, or shared helper modules with concrete code diffs. Warns against premature abstraction (single-use helpers).
When to use it
- Test suite has grown to 20+ files with copy-paste duplication.
- Onboarding pain because new tests are written by copying existing ones.
- Adding shared concerns (logging, instrumentation) consistently across tests.
- Refactoring before a major framework upgrade — DRY first, then upgrade is easier.
The prompt
XML-tagged — best for Claude 4.x
<role>
You are a test infrastructure engineer. You know that DRY in tests is a balance — too much abstraction hides intent; too little creates rot. You propose refactors that pay back in maintenance, not premature ones.
</role>
<context>
Common DRY opportunities in tests:
- **beforeEach duplication** — same setup steps in multiple files → fixture
- **Helper duplication** — same helper function defined inline in multiple files → shared module
- **Assertion pattern duplication** — same group of assertions on the same object shape → custom matcher / assertion helper
- **Test data duplication** — same fixtures (users, products) created inline → factory function
- **POM duplication** — same UI flow scripted in multiple specs → POM method
Anti-pattern: extracting a helper used ONLY ONCE. Inline > abstraction when called from one place.
</context>
<task>
For the test files I provide:
1. Identify EXACT duplication (3+ occurrences of same logic).
2. Identify NEAR duplication (2+ occurrences with minor variation).
3. Propose refactor per duplication:
- For setup → Playwright fixture (or Jest `beforeEach` helper)
- For data → factory function
- For assertion → custom matcher or assertion helper
- For UI flow → POM method
4. Diff-style output showing the new shared module + per-file diff.
5. Warn against premature abstraction — single-use helpers should be inlined.
</task>
<input>
Test files (paths + content): {test_files}
Framework: {framework}
Existing shared modules (if any): {existing_shared}
</input>
<constraints>
- Threshold: 3+ exact duplications, OR 2+ near-duplications with > 80% similarity.
- Single-use helpers FLAG as anti-pattern, not as refactor candidate.
- Diffs MUST be diff-style (—/+) showing exact lines added/removed.
- Suggested abstraction names should be domain-specific (not `utilA`, `helperX`).
- Note any shared concern that's organizational (e.g., logging) vs functional (test logic).
</constraints>
<output_format>
Three sections:
1. **Duplication inventory** — table: Pattern | Occurrences | Files | Recommended refactor
2. **Refactor diffs** — per refactor, show new shared file + per-file modification
3. **Warnings** — flag single-use helpers and other premature-abstraction risks
</output_format>
Before writing, count occurrences of each candidate pattern — single occurrences are NOT refactor candidates.Example
Common pitfalls
- Model proposes extracting single-use helpers — anti-pattern; force the 3+ occurrence rule.
- Refactors lose context (helpers named `helper1`, `utilA`); insist on domain-named abstractions.
- Diffs aren't really diffs (just rewritten files) — make sure — / + format is used.
- Over-abstracts data (factory for a 2-line user object) — sometimes inline data is clearer.
Tips
- Refactor in a separate PR — don't bundle DRY refactor with new test additions.
- After refactor, run the whole suite to ensure behavior is unchanged.
- Pair with `generate-playwright-pom` for UI flows that deserve POM extraction.
- Pair with `pom-refactoring-reviewer` to verify the new abstractions don't violate POM principles.
FAQ
When test setup becomes a chain of abstractions that obscures what the test is actually exercising. If you have to navigate through 3 helper files to understand a single test, the abstractions are too deep. Inline beats abstraction when an abstraction has only 2-3 callers.
Related prompts
Review Test Code for Anti-Patterns
Reads a test file and returns a categorized list of anti-patterns — hard sleeps, shared mutable state, weak assertions (`toBeTruthy` instead of `toEqual`), missing teardown, mixed setup/assertion concerns — each with line numbers, severity, and a suggested fix.
Open →Generate Playwright Page Object Model
Give the model a page description plus a list of UI elements and it returns a complete Page Object Model in TypeScript using Playwright's auto-waiting locators (getByRole / getByTestId), typed action and assertion methods, and a page-level fixture.
Open →Page Object Model Refactoring Reviewer
Reviews a Page Object Model class and returns specific refactoring suggestions — locator priority (role > label > testid > CSS), action vs assertion separation, action granularity (one method per user intent), and constructor cleanliness — with diff-style proposed changes.
Open →Test Code Quality Checklist
Returns a per-test-file quality checklist with 20-30 items grouped by category (naming / structure / assertions / isolation / performance / maintainability) — each marked PASS/FAIL with one-line evidence from the code.
Open →