app-store
App Store optimization and marketing skills for descriptions, screenshots, keywords, review responses, and comprehensive…
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.
Claude Code
$ npx -y skills add rshankras/claude-code-apple-skills --skill characterization-test-generator --agent claude-code
Codex
$ npx skills add rshankras/claude-code-apple-skills --skill characterization-test-generator -a codex -y
Cursor
$ npx skills add rshankras/claude-code-apple-skills --skill characterization-test-generator -a cursor -y
Gemini CLI
$ npx skills add rshankras/claude-code-apple-skills --skill characterization-test-generator -a gemini-cli -y
GitHub Copilot
$ npx skills add rshankras/claude-code-apple-skills --skill characterization-test-generator -a github-copilot -y
OpenCode
$ npx skills add rshankras/claude-code-apple-skills --skill characterization-test-generator -a opencode -y
Windsurf
$ npx skills add rshankras/claude-code-apple-skills --skill characterization-test-generator -a windsurf -y
name: characterization-test-generator description: 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. allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion] last_verified: 2026-07-16 review_by: 2027-06-22
Generate tests that document what existing code **actually does** — not what it should do. These tests capture current behavior so you can refactor with confidence, especially when using AI to modify code.
Use this skill when the user:
AI refactoring is powerful but risky:
Glob: **/*.swift (in the target module) Grep: "class |struct |enum |protocol |func " (public API surface)
Identify:
For each public method, classify:
| Category | Example | Test Strategy | |----------|---------|---------------| | Pure computation | `calculate(a, b) -> c` | Input/output pairs | | State mutation | `addItem(_:)` modifies array | Before/after state checks | | Async operation | `fetchData() async -> [Item]` | Mock dependencies, verify results | | Side effect | `save()` writes to disk | Verify mock was called | | Event emission | `delegate?.didUpdate()` | Capture delegate calls | | Error path | Throws on invalid input | Verify correct error type |
Characterization tests should be clearly labeled:
import Testing
@testable import YourApp
@Suite("Characterization: ItemManager")
struct ItemManagerCharacterizationTests {
// Tests document CURRENT behavior, not ideal behavior
}@Test("current behavior: calculates total with tax")
func calculatesTotal() {
let calculator = PriceCalculator()
let result = calculator.total(subtotal: 100.0, taxRate: 0.08)
// Document actual behavior — even if the rounding seems wrong
#expect(result == 108.0)
}@Test("current behavior: addItem appends and sorts by date")
func addItemSortsbyDate() {
let manager = ItemManager()
let older = Item(title: "A", date: .distantPast)
let newer = Item(title: "B", date: .now)
manager.addItem(older)
manager.addItem(newer)
// Document actual ordering behavior
#expect(manager.items.first?.title == "A")
#expect(manager.items.last?.title == "B")
#expect(manager.items.count == 2)
}@Test("current behavior: loadItems returns cached data when offline")
func loadItemsOffline() async throws {
let mockNetwork = MockNetworkClient(shouldFail: true)
let mockCache = MockCache(items: [Item.sample])
let service = ItemService(network: mockNetwork, cache: mockCache)
let items = try await service.loadItems()
// Document: falls back to cache when network fails
#expect(items.count == 1)
#expect(items.first?.title == Item.sample.title)
}@Test("current behavior: save writes to UserDefaults")
func saveWritesToDefaults() {
let defaults = MockUserDefaults()
let settings = SettingsManager(defaults: defaults)
settings.setTheme(.dark)
settings.save()
// Document: saves as string, not as enum raw value
#expect(defaults.lastSetValue as? String == "dark")
#expect(defaults.lastSetKey == "app_theme")
}@Test("current behavior: throws on empty title")
func throwsOnEmptyTitle() {
let validator = ItemValidator()
#expect(throws: ValidationError.emptyField("title")) {
try validator.validate(Item(title: "", date: .now))
}
}@Test("current behavior: handles nil optional gracefully")
func handlesNilOptional() {
let parser = DataParser()
let result = parser.parse(data: nil)
// Document: returns empty array on nil, doesn't crash
#expect(result.isEmpty)
}
@Test("current behavior: handles empty collection")
func handlesEmptyCollection() {
let aggregator = StatsAggregator()
let stats = aggregator.compute(values: [])
// Document: returns zeroes, not NaN or crash
#expect(stats.average == 0.0)
#expect(stats.count == 0)
}This is the key step. For each test:
1. **Read the source code** to understand what the method actually returns 2. **Trace the logic** for the given inputs 3. **Write the assertion with the actual value**
// ❌ Wrong — this is what you WANT it to do #expect(result == expectedCorrectValue) // ✅ Right — this is what it ACTUALLY does #expect(result == actualCurrentValue) // Note: off-by-one, but current behavior
**Add comments for surprising behavior:**
// CHARACTERIZATION: This returns 11 not 10 due to inclusive range. // Don't "fix" this until intentionally changing behavior. #expect(range.count == 11)
1. **Run all characterization tests** —
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.
App Store optimization and marketing skills for descriptions, screenshots, keywords, review responses, and comprehensive…
Privacy-preserving ad measurement with AdAttributionKit (SKAdNetwork's successor) — install and re-engagement attribution,…
Generate compelling App Store descriptions that convert browsers into users. Use when writing initial descriptions, improving…
Apple Search Ads campaign strategy for indie developers — paid acquisition, keyword bidding, budget planning, and ROAS…
Take a one-time in-app purchase from MISSING_METADATA to READY_TO_SUBMIT in App Store Connect — set its price schedule and…
Optimize app title, subtitle, and keywords for maximum App Store discoverability. Use when launching a new app, improving search…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.