Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
rshankras avatar

Test Data Factory

  • 3 installs
  • 591 repo stars
  • Updated July 24, 2026
  • rshankras/claude-code-apple-skills

Generates test fixture factories for your models using the builder pattern and static factories for zero-boilerplate test data.

About

Generates factory helpers using the builder pattern and static factories to create test data with minimal boilerplate. A developer uses it when tests need easy sample-data setup.

  • Builder pattern and static factories
  • Eliminates test-setup boilerplate

Test Data Factory by the numbers

  • 3 all-time installs (skills.sh)
  • +1 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #1,649 of 2,153 Testing & QA skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rshankras/claude-code-apple-skills --skill test-data-factory

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3
repo stars591
Last updatedJuly 24, 2026
Repositoryrshankras/claude-code-apple-skills

What it does

Generates test fixture factories for your models using the builder pattern and static factories for zero-boilerplate test data.

Files

SKILL.mdMarkdownGitHub ↗

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

// ❌ 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
// 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:

// 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:

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:

// 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:

// 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 TypeDefault Strategy
UUIDUUID() (unique per call)
StringDescriptive placeholder ("Test Item")
DateFixed timestamp (not Date() — causes flaky tests)
Boolfalse (opt-in to special states)
ArrayEmpty [] (opt-in to populated)
Optionalnil (opt-in to having a value)
EnumMost common/default case
Nested modelThat model's .fixture()

Naming Conventions

// 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

## 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

// 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 data

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.