test-data-factory
Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.
Best use case
test-data-factory is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.
Teams using test-data-factory should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/test-data-factory/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How test-data-factory Compares
| Feature / Agent | test-data-factory | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# Test Data Factory
Generate factory helpers that make creating test data effortless. Eliminates boilerplate in test setup so writing tests has zero friction.
## When This Skill Activates
Use this skill when the user:
- Has repetitive test setup code
- Asks for "test fixtures" or "test factories" or "sample data"
- Wants to reduce boilerplate in tests
- Says "my tests have too much setup"
- Is building a test suite and needs realistic sample data
- Mentions "builder pattern" for tests
## Why Test Factories
```swift
// ❌ Without factory — every test repeats this
let item = Item(
id: UUID(),
title: "Test Item",
description: "A test description",
category: .general,
createdAt: Date(),
updatedAt: Date(),
isFavorite: false,
tags: [],
author: User(id: UUID(), name: "Test User", email: "test@test.com")
)
// ✅ With factory — one line, override only what matters
let item = Item.fixture()
let favoriteItem = Item.fixture(isFavorite: true)
let taggedItem = Item.fixture(tags: ["swift", "testing"])
```
## Process
### Phase 1: Discover Models
```
Glob: **/*.swift (in source targets)
Grep: "struct.*:.*Identifiable|class.*:.*Identifiable|@Model"
Grep: "struct.*:.*Codable|struct.*:.*Sendable"
```
Identify models that appear in test files:
```
Grep: "let.*=.*Model(" in test targets (manual construction)
```
### Phase 2: Choose Factory Pattern
Ask via AskUserQuestion:
1. **Factory style?**
- Static factory methods (simpler, recommended)
- Builder pattern (more flexible, for complex models)
- Both
2. **Where to add?**
- Test target extension (recommended — keeps production code clean)
- Shared test helper file
### Phase 3: Generate Factories
#### Pattern 1: Static Factory Extension
```swift
// Tests/Factories/Item+Factory.swift
import Foundation
@testable import YourApp
extension Item {
/// Creates a test fixture with sensible defaults.
/// Override only the properties relevant to your test.
static func fixture(
id: UUID = UUID(),
title: String = "Test Item",
description: String = "A test description",
category: Category = .general,
createdAt: Date = Date(timeIntervalSince1970: 1_700_000_000),
updatedAt: Date = Date(timeIntervalSince1970: 1_700_000_000),
isFavorite: Bool = false,
tags: [String] = [],
author: User = .fixture()
) -> Item {
Item(
id: id,
title: title,
description: description,
category: category,
createdAt: createdAt,
updatedAt: updatedAt,
isFavorite: isFavorite,
tags: tags,
author: author
)
}
/// Named fixtures for common test scenarios
static var sample: Item { .fixture() }
static var favorite: Item { .fixture(isFavorite: true) }
static var empty: Item { .fixture(title: "", description: "") }
/// Collection fixtures
static var sampleList: [Item] {
[
.fixture(id: UUID(), title: "First Item", category: .work),
.fixture(id: UUID(), title: "Second Item", category: .personal),
.fixture(id: UUID(), title: "Third Item", category: .general)
]
}
}
extension User {
static func fixture(
id: UUID = UUID(),
name: String = "Test User",
email: String = "test@example.com"
) -> User {
User(id: id, name: name, email: email)
}
static var sample: User { .fixture() }
}
```
#### Pattern 2: Builder Pattern
For models with many optional fields or complex relationships:
```swift
// Tests/Factories/ItemBuilder.swift
@testable import YourApp
final class ItemBuilder {
private var id: UUID = UUID()
private var title: String = "Test Item"
private var description: String = "A test description"
private var category: Category = .general
private var createdAt: Date = .init(timeIntervalSince1970: 1_700_000_000)
private var isFavorite: Bool = false
private var tags: [String] = []
private var author: User = .fixture()
@discardableResult
func with(title: String) -> Self {
self.title = title
return self
}
@discardableResult
func with(category: Category) -> Self {
self.category = category
return self
}
@discardableResult
func favorited() -> Self {
self.isFavorite = true
return self
}
@discardableResult
func with(tags: [String]) -> Self {
self.tags = tags
return self
}
@discardableResult
func authored(by user: User) -> Self {
self.author = user
return self
}
func build() -> Item {
Item(
id: id,
title: title,
description: description,
category: category,
createdAt: createdAt,
updatedAt: createdAt,
isFavorite: isFavorite,
tags: tags,
author: author
)
}
}
// Usage:
let item = ItemBuilder()
.with(title: "Important")
.with(category: .work)
.favorited()
.build()
```
#### Pattern 3: Sequence Factories
For generating unique test data in loops:
```swift
extension Item {
/// Creates N unique items with sequential titles
static func fixtures(count: Int) -> [Item] {
(0..<count).map { index in
.fixture(
id: UUID(),
title: "Item \(index + 1)"
)
}
}
/// Creates items matching specific states for state-based testing
static var allStates: [Item] {
[
.fixture(title: "Draft", category: .draft),
.fixture(title: "Active", category: .active),
.fixture(title: "Archived", category: .archived),
.fixture(title: "Deleted", category: .deleted)
]
}
}
```
### Phase 4: Generate Date/Time Helpers
Tests with dates are notoriously flaky. Provide fixed dates:
```swift
// Tests/Factories/Date+Factory.swift
extension Date {
/// Fixed reference dates for deterministic tests
static let testReference = Date(timeIntervalSince1970: 1_700_000_000) // 2023-11-14
static let testYesterday = testReference.addingTimeInterval(-86_400)
static let testLastWeek = testReference.addingTimeInterval(-604_800)
static let testNextMonth = testReference.addingTimeInterval(2_592_000)
/// Create a date relative to test reference
static func testDate(daysFromReference days: Int) -> Date {
testReference.addingTimeInterval(TimeInterval(days * 86_400))
}
}
```
### Phase 5: Generate Mock Response Factories
For network/API testing:
```swift
// Tests/Factories/APIResponse+Factory.swift
extension APIResponse where T == [Item] {
static func success(items: [Item] = Item.sampleList) -> APIResponse {
APIResponse(data: items, statusCode: 200, error: nil)
}
static func empty() -> APIResponse {
APIResponse(data: [], statusCode: 200, error: nil)
}
static func error(_ error: APIError = .serverError) -> APIResponse {
APIResponse(data: nil, statusCode: 500, error: error)
}
static func notFound() -> APIResponse {
APIResponse(data: nil, statusCode: 404, error: .notFound)
}
}
```
## Factory Design Rules
### Defaults Should Be
| Property Type | Default Strategy |
|--------------|-----------------|
| UUID | `UUID()` (unique per call) |
| String | Descriptive placeholder (`"Test Item"`) |
| Date | Fixed timestamp (not `Date()` — causes flaky tests) |
| Bool | `false` (opt-in to special states) |
| Array | Empty `[]` (opt-in to populated) |
| Optional | `nil` (opt-in to having a value) |
| Enum | Most common/default case |
| Nested model | That model's `.fixture()` |
### Naming Conventions
```swift
// Static factory — use .fixture() for customizable, .sample for quick
Item.fixture(title: "Custom") // Customizable
Item.sample // Quick default
Item.sampleList // Collection
// Named scenarios
Item.favorite // Specific state
Item.expired // Specific state
Item.empty // Edge case
// Builder — use descriptive method names
ItemBuilder().favorited().build()
ItemBuilder().with(title: "X").build()
```
## Output Format
```markdown
## Test Data Factories Generated
### Models Covered
| Model | Factory Type | Named Fixtures | Collection Fixtures |
|-------|-------------|----------------|-------------------|
| Item | Static + Builder | sample, favorite, empty | sampleList, fixtures(count:) |
| User | Static | sample | — |
| APIResponse | Static | success, empty, error | — |
### Files Created
- `Tests/Factories/Item+Factory.swift`
- `Tests/Factories/User+Factory.swift`
- `Tests/Factories/ItemBuilder.swift`
- `Tests/Factories/Date+Factory.swift`
- `Tests/Factories/APIResponse+Factory.swift`
### Usage Example
```swift
// Before (30 lines of setup)
let user = User(id: UUID(), name: "Test", email: "t@t.com")
let item = Item(id: UUID(), title: "T", description: "D", ...)
// After (1 line)
let item = Item.fixture(isFavorite: true)
```
```
## References
- `generators/test-generator/` — generates tests that use these factories
- `testing/tdd-feature/` — TDD workflow benefits from low-friction factories
- `testing/integration-test-scaffold/` — integration tests need realistic dataRelated Skills
test-contract
Generate protocol/interface test suites that any implementation must pass. Define the contract once, test every implementation. Use when designing protocols or swapping implementations.
snapshot-test-setup
Set up SwiftUI visual regression testing with swift-snapshot-testing. Generates snapshot test boilerplate and CI configuration. Use for UI regression prevention.
integration-test-scaffold
Generate cross-module test harness with mock servers, in-memory stores, and test configuration. Use when testing networking + persistence + business logic together.
characterization-test-generator
Generates tests that capture current behavior of existing code before refactoring. Use when you need a safety net before AI-assisted refactoring or modifying legacy code.
testing
TDD and testing skills for iOS/macOS apps. Covers characterization tests, TDD workflows, test contracts, snapshot tests, and test infrastructure. Use for test-driven development, adding tests to existing code, or building test infrastructure.
test-spec
Generates comprehensive test specification with unit tests, UI tests, accessibility testing, and beta testing plan. Creates TEST_SPEC.md from PRD and implementation specs. Use when creating QA strategy.
beta-testing
Beta testing strategy for iOS/macOS apps. Covers TestFlight program setup, beta tester recruitment, feedback collection methodology, user interviews, signal-vs-noise interpretation, and go/no-go launch readiness decisions. Use when planning a beta, setting up TestFlight, collecting user feedback, or deciding if ready to launch.
swiftdata-architecture
Deep dive into SwiftData design patterns and best practices. Covers schema design, query patterns, repository pattern, and performance optimization. Use when designing data models or improving SwiftData usage.
test-generator
Generate test templates for unit tests, integration tests, and UI tests using Swift Testing and XCTest. Use when adding tests to iOS/macOS apps.
data-export
Generates data export/import infrastructure for JSON, CSV, PDF formats with GDPR data portability, share sheet integration, and file import. Use when user wants data export functionality, CSV/JSON/PDF export, GDPR compliance data portability, import from files, or share sheet for data.
watchOS
watchOS development guidance including SwiftUI for Watch, Watch Connectivity, complications, and watch-specific UI patterns. Use for watchOS code review, best practices, or Watch app development.
visionos-widgets
visionOS widget patterns including mounting styles, glass/paper textures, proximity-aware layouts, and spatial widget families. Use when creating or adapting widgets for visionOS.