Skip to content
Development
Skill

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

From plugin
rshankras-apple-skills
848181 skills

Claude Code

$ npx -y skills add rshankras/claude-code-apple-skills --skill test-data-factory --agent claude-code

SKILL.md

test-data-factory.SKILL.md
name: test-data-factory
description: Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]
last_verified: 2026-07-16
review_by: 2027-06-22

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: .
Read more
@rshankras
Ships withrshankras-apple-skills

A collection of Claude Code skills for iOS, macOS, watchOS, visionOS, and Apple platform development. These skills help you plan and build apps, maintain code quality, ensure HIG compliance, and guide you from idea to App Store.

Stars on GitHub

Momentum

stars in total
848
Star history of rshankras/claude-code-apple-skills on GitHub, a chart by star-history.com

Other skills on rshankras-apple-skills.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about test-data-factory.

Which coding agents can use test-data-factory?
test-data-factory installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.