Helps developers avoid common testing anti-patterns and write more reliable tests.
This skill appears to be prompt/documentation-only, with no required secrets, no remote endpoints, and no evident code execution or data access capability, so overall risk is low. For supply chain, it is open-source on GitHub and auditable, but limited adoption and unknown maintenance suggest basic provenance checks before use.
The material explicitly states that no keys or environment variables are required; it is guidance about testing anti-patterns and shows no path for credential collection, storage, or misuse.
No remote endpoints are declared, and the system flags it as prompt-only; there is no indicated mechanism for sending user data to external services.
This is a documentation-style skill description with no installation or runtime requirement to spawn local processes, execute scripts, or use system capabilities; the code snippets are illustrative only.
It does not request permission to read or write local files, repositories, databases, or other resources; based on the material, it has no practical data access surface.
The source is an open-source GitHub repository and is in principle auditable, which is a positive factor; however, the license is undeclared, community adoption is low (0 stars), and maintenance status is unknown, so provenance continuity and audit depth warrant caution.
Copy the install command and let the AI configure it · recommended for beginners
Please install the "Testing Anti-Patterns" skill from askskill: 1. Download https://raw.githubusercontent.com/obra/clank/main/skills/testing/testing-anti-patterns/SKILL.md 2. Save it as ~/.claude/skills/testing-anti-patterns/SKILL.md 3. Reload skills and tell me it's ready
Please review the following unit tests for anti-patterns. Focus on whether they test mock behavior, add test-only methods to production classes, or mock dependencies before understanding them. Point out each issue and suggest improvements.
A checklist of testing issues with reasons and refactoring suggestions for each anti-pattern.
The following tests rely too heavily on mocks and fail whenever implementation details change. Rewrite them by reducing mock-behavior assertions, validating business outcomes instead, and keeping only necessary isolation. Explain your changes.
A more robust version of the tests plus an explanation of why the refactoring improves them.
I am writing tests for a service class. Based on the dependency graph below, analyze which dependencies should be mocked and which should not, and explain the reasoning, such as external systems, stable value objects, database access, time, or randomness.
A dependency classification guide that helps choose proper test boundaries and mocking strategy.
Tests must verify real behavior, not mock behavior. Mocks are a means to isolate, not the thing being tested.
Core principle: Test what the code does, not what the mocks do.
Following strict TDD prevents these anti-patterns.
1. NEVER test mock behavior
2. NEVER add test-only methods to production classes
3. NEVER mock without understanding dependencies
The violation:
// ❌ BAD: Testing that the mock exists
test('renders sidebar', () => {
render(<Page />);
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
});
Why this is wrong:
your human partner's correction: "Are we testing the behavior of a mock?"
The fix:
// ✅ GOOD: Test real component or don't mock it
test('renders sidebar', () => {
render(<Page />); // Don't mock sidebar
expect(screen.getByRole('navigation')).toBeInTheDocument();
});
// OR if sidebar must be mocked for isolation:
// Don't assert on the mock - test Page's behavior with sidebar present
BEFORE asserting on any mock element:
Ask: "Am I testing real component behavior or just mock existence?"
IF testing mock existence:
STOP - Delete the assertion or unmock the component
Test real behavior instead
The violation:
// ❌ BAD: destroy() only used in tests
class Session {
async destroy() { // Looks like production API!
await this._workspaceManager?.destroyWorkspace(this.id);
// ... cleanup
}
}
// In tests
afterEach(() => session.destroy());
Why this is wrong:
The fix:
// ✅ GOOD: Test utilities handle test cleanup
// Session has no destroy() - it's stateless in production
// In test-utils/
export async function cleanupSession(session: Session) {
const workspace = session.getWorkspaceInfo();
if (workspace) {
await workspaceManager.destroyWorkspace(workspace.id);
}
}
// In tests
afterEach(() => cleanupSession(session));
BEFORE adding any method to production class:
Ask: "Is this only used by tests?"
IF yes:
STOP - Don't add it
Put it in test utilities instead
Ask: "Does this class own this resource's lifecycle?"
IF no:
STOP - Wrong class for this method
The violation:
// ❌ BAD: Mock breaks test logic
test('detects duplicate server', () => {
// Mock prevents config write that test depends on!
vi.mock('ToolCatalog', () => ({
discoverAndCacheTools: vi.fn().mockResolvedValue(undefined)
}));
await addServer(config);
await addServer(config); // Should throw - but won't!
});
Why this is wrong:
The fix:
// ✅ GOOD: Mock at correct level
test('detects duplicate server', () => {
// Mock the slow part, preserve behavior test needs
vi.mock('MCPServerManager'); // Just mock slow server startup
await addServer(config); // Config written
await addServer(config); // Duplicate detected ✓
});
BEFORE mocking any method:
STOP - Don't mock yet
1. Ask: "What side effects does the real method have?"
2. Ask: "Does this test depend on any of those side effects?"
3. Ask: "Do I fully understand what this test needs?"
IF depends on side effects:
…
Write evergreen comments focused on what and why, not historical context.
Compare 2-3 approaches before execution to choose a stronger solution.
Plan with pseudocode first, refine approaches, then translate into working code.
Search past Claude Code chats to recover facts, decisions, and context.
Design systems by hiding implementation details behind domain-level interfaces.
Name code by domain meaning to improve clarity and team alignment.
Identify test anti-patterns and improve tests without polluting production code.
Write behavior-focused, refactor-resistant tests that verify intent and regressions.
Use test-first development to improve code quality and maintainability.
Write failing tests first to implement features and bug fixes reliably.
Build high-quality Kotlin tests with Kotest, MockK, coroutines, and coverage.
Learn Rust testing patterns and TDD to improve code quality and reliability.