skills/coding/setup-test-data/SKILL.md
Master test data setup: creating meaningful test fixtures, test data factories, and managing test data lifecycle. Use when user needs test data, test fixtures, sample data for tests, or when tests are hard to maintain due to data setup. Triggers especially when user says "test fixtures", "test data", "setup test", "create test objects", or "sample data".
npx skillsauth add ImaginerLabs/skill-manager setup-test-dataInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Setup-test-data is a behavioral specification skill that encapsulates the methodology for creating maintainable, meaningful test data that makes tests readable and robust.
This skill embodies the expertise of developers who've written tests with messy inline data and those who've used well-designed fixtures — and know the difference in maintainability.
"Test data should tell a story. When you read a test, you should immediately understand what scenario it's testing without deciphering random strings or magic numbers."
┌─────────────────────────────────────────────────────────────┐
│ TEST DATA QUALITY │
│ │
│ BAD TEST DATA: GOOD TEST DATA: │
│ ───────────── ────────────── │
│ const x = "asdf"; const activeUser = {...}; │
│ const y = 12345; const premiumUser = {...}; │
│ const z = true; const guestUser = {...}; │
│ │
│ Meaningless Self-documenting │
│ Hard to understand Clear intent │
│ Brittle Flexible │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ TEST DATA STRATEGY MATRIX │
│ │
│ STRATEGY USE WHEN AVOID WHEN │
│ ───────── ───────── ────────── │
│ Inline data Simple, one-off Repeated use │
│ Constants Shared values Complex objects │
│ Factories Dynamic creation Simple tests │
│ Fixtures Complex state Fast tests needed │
│ Builders Many optional fields Simple tests │
└─────────────────────────────────────────────────────────────┘
| Approach | Best For | Avoid When | |----------|---------|-----------| | Inline | One test, simple case | Multiple tests, complex data | | Constants | Shared test values | Tests need variations | | Factories | Creating variations | Setup is complex | | Fixtures | Shared complex state | Data changes frequently | | Builders | Flexible object creation | Simple data |
// ❌ BAD: What is this?
const user = {
id: 123,
name: "John",
email: "[email protected]",
active: true,
};
// ✅ GOOD: Clear from context
const testUser = {
id: "user_test_123",
email: "[email protected]",
name: "Test User",
role: "customer",
isActive: true,
};
// Even better: Named for the scenario
const activeCustomer = {
id: "customer_active_001",
email: "[email protected]",
status: "active",
subscription: "premium",
};
const inactiveUser = {
id: "user_inactive_001",
email: "[email protected]",
status: "inactive",
subscription: null,
};
// ❌ BAD: No context
const result = calculate(100, 20);
// ✅ GOOD: Clear expectations
const order = {
subtotal: 100,
taxRate: 0.2,
expectedTotal: 120,
};
const result = calculate(order.subtotal, order.taxRate);
expect(result).toBe(order.expectedTotal);
// Factory for flexible test object creation
function createUser(overrides?: Partial<User>): User {
const defaultUser: User = {
id: "user_default_001",
email: "[email protected]",
name: "Default User",
role: "customer",
isActive: true,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
};
return { ...defaultUser, ...overrides };
}
// Usage: Create variations easily
const activeUser = createUser({ isActive: true });
const adminUser = createUser({ role: "admin" });
const inactiveUser = createUser({ isActive: false });
const premiumUser = createUser({ subscription: "premium" });
// Builder for complex objects
class UserBuilder {
private user: Partial<User> = {
id: "user_test_001",
};
withName(name: string): this {
this.user.name = name;
return this;
}
withEmail(email: string): this {
this.user.email = email;
return this;
}
asAdmin(): this {
this.user.role = "admin";
this.user.isAdmin = true;
return this;
}
withPremiumSubscription(): this {
this.user.subscription = "premium";
this.user.subscriptionEndsAt = new Date("2025-01-01");
return this;
}
build(): User {
return { ...defaultUser, ...this.user } as User;
}
}
// Usage: Chain readable methods
const premiumAdmin = new UserBuilder()
.withName("Premium Admin")
.withEmail("[email protected]")
.asAdmin()
.withPremiumSubscription()
.build();
// Shared fixtures for complex state
const sharedFixtures = {
// Database state
emptyDatabase: async () => {
await db.clear();
},
databaseWithUsers: async () => {
await db.clear();
await db.users.bulkCreate([
createUser({ name: "User 1" }),
createUser({ name: "User 2" }),
]);
},
// Complex business state
orderInProgress: (): Order => ({
id: "order_pending_001",
status: "pending",
items: [
{ productId: "prod_1", quantity: 2, price: 10 },
],
customer: createCustomer({ name: "Pending Customer" }),
}),
orderShipped: (): Order => ({
...orderInProgress(),
status: "shipped",
shippedAt: new Date(),
trackingNumber: "TRACK123",
}),
};
// Usage in tests
beforeEach(async () => {
await sharedFixtures.emptyDatabase();
});
it("should process order", async () => {
const order = sharedFixtures.orderInProgress();
const result = await processOrder(order);
expect(result.status).toBe("completed");
});
// ❌ BAD: Random-looking data
const payment = {
amount: 938475,
currency: "USD",
card: "4111111111111111",
};
// ✅ GOOD: Intent-revealing data
const payment = {
amount: 99.99, // Clear price point
currency: "USD",
card: "4111111111111111", // Valid test card number
};
// Explicit edge cases
const testCases = {
emptyString: { name: "" },
singleCharacter: { name: "A" },
veryLong: { name: "A".repeat(1000)) },
unicode: { name: "日本語テスト" },
sqlInjection: { name: "'; DROP TABLE users; --" },
xssAttempt: { name: "<script>alert('xss')</script>" },
};
// Easy to find and understand
it.each([
["empty string", testCases.emptyString],
["single character", testCases.singleCharacter],
["very long name", testCases.veryLong],
])("should handle %s", (caseName, data) => {
// Test logic
});
// ❌ BAD: Fake-looking
const user = {
name: "John Doe",
email: "[email protected]",
company: "XYZ Corp",
};
// ✅ GOOD: Realistic
const user = {
name: "Sarah Chen",
email: "[email protected]",
company: "Acme Technologies",
role: "Senior Software Engineer",
department: "Platform Engineering",
};
// BEFORE: 50 lines of setup
it("should send email when order ships", async () => {
const user = {
id: "user_123",
email: "[email protected]",
name: "Test User",
preferences: { emailNotifications: true },
// ... 20 more fields
};
const order = {
id: "order_456",
items: [...],
shippingAddress: {...},
// ... 15 more fields
};
// 100 lines of setup for a simple test
});
// AFTER: Factory with meaningful defaults
it("should send email when order ships", async () => {
const user = createUser({
email: "[email protected]",
preferences: { emailNotifications: true },
});
const order = createOrder({
status: "pending",
customer: user,
});
// 10 lines of setup, clear intent
});
// PROBLEM: Hard-coded dates break over time
const user = {
createdAt: new Date("2024-01-01"),
subscriptionEnds: new Date("2024-12-31"),
};
// SOLUTION: Relative dates
const user = {
createdAt: subDays(new Date(), 30), // 30 days ago
subscriptionEnds: addDays(new Date(), 335), // ~1 year from now
};
// OR: Stable fixture dates
const FIXED_DATE = new Date("2024-06-15T12:00:00Z");
const user = {
createdAt: FIXED_DATE,
};
// BEFORE: Repeated setup
it("should handle premium user", () => {
const user = createUser({ subscription: "premium" });
// test
});
it("should handle free user", () => {
const user = createUser({ subscription: "free" });
// test
});
it("should handle expired subscription", () => {
const user = createUser({ subscription: "expired" });
// test
});
// AFTER: Parametrized tests
describe.each([
["premium", "premium"],
["free", "free"],
["expired", "expired"],
])("subscription type: %s", (name, subscription) => {
it("should handle correctly", () => {
const user = createUser({ subscription });
// test once, covers all
});
});
// ❌ BAD
if (user.permissions === 0b1001) { ... }
// ✅ GOOD
const PERMISSIONS = {
READ: 1,
WRITE: 2,
DELETE: 4,
ADMIN: 8,
};
if (user.permissions === PERMISSIONS.READ | PERMISSIONS.WRITE) { ... }
// ❌ BAD
it("test 1", () => {
const user = { name: "Test", email: "[email protected]" };
// ...
});
it("test 2", () => {
const user = { name: "Test", email: "[email protected]" }; // Duplicated!
// ...
});
// ✅ GOOD
const testUser = { name: "Test", email: "[email protected]" };
it("test 1", () => {
// use testUser
});
it("test 2", () => {
// use testUser
});
// ❌ BAD: Fixture does too much
const userFixture = {
// 100 fields with obscure defaults
// Helper methods that complicate things
// Complex setup logic
};
// ✅ GOOD: Composable, focused fixtures
const baseUser = { /* essential fields */ };
const adminUser = { ...baseUser, role: "admin" };
const premiumUser = { ...baseUser, subscription: "premium" };
TEST DATA DESIGN CHECKLIST
===========================
□ 1. Can you understand the test from the data alone?
□ 2. Is the data self-documenting?
□ 3. Does the name reveal intent?
□ 4. Are edge cases explicit?
□ 5. Is the data realistic?
□ 6. Can you create variations easily?
□ 7. Is setup minimal but complete?
□ 8. Will this break in 6 months?
□ 9. Can someone new understand this?
□ 10. Is there any magic data (explain if necessary)?
PATTERN SELECTION:
□ Inline → Simple, one-off test
□ Constants → Shared values across tests
□ Factory → Dynamic creation with defaults
□ Builder → Complex objects with many options
□ Fixture → Shared complex state
The test data should tell you what scenario is being tested without reading the test logic.
Variables and values should explain themselves. No need for extra comments.
Build test objects from smaller pieces, not one giant fixture.
Use relative dates or fixed test dates. Don't let tests break naturally.
Use real-world patterns but controlled values. Credit card numbers should pass validation.
test-think — Decides what test data is neededgenerate-mock — Often used alongside test dataintelligent-test-creation — Combines with test designdebug-test — When test data causes failurestest-readability — Data organization affects readabilitydevelopment
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation.
devops
Create a new implementation plan file for new features, refactoring existing code or upgrading packages, design, architecture or infrastructure.
tools
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
documentation
Generates standardized porting documentation from completed feature changes. Analyzes commit diffs or file contents, extracts change intent, and outputs Markdown documentation for cross-team understanding. Should be used when the user needs to document a change for cross-team or cross-project consumption. Distinguished from cross-branch-fix-porter which actively re-implements fixes, this skill documents changes.