- name
- swift-xctest
- description
- Swift 6 + XCTest testing patterns for macOS/iOS apps using SwiftData, EventKit, and SwiftUI
- domain
- ios-macos
- homepage
- https://github.com/soponcd/timeflow-skills/tree/main/teams/skills/swift-xctest
- metadata
- clawdbot
- emoji
- 🧩
Swift/XCTest Testing Skill
Expert-level XCTest patterns for Swift 6 macOS/iOS applications. Specialized for SwiftData, EventKit, SwiftUI, and strict concurrency.
When to Use
Use this skill when:
- Writing XCTest for Swift 6 applications
- Testing SwiftData models with in-memory containers
- Testing Swift 6 actors and
@MainActorisolation - Testing EventKit integrations
- Testing SwiftUI views and @Observable ViewModels
- Writing performance tests for macOS apps
Core Principles
1. SwiftData Testing Pattern
import SwiftData
import XCTest
@MainActor
final class ModelTests: XCTestCase {
var container: ModelContainer!
var context: ModelContext!
override func setUp() async throws {
try await super.setUp()
// Use in-memory config for isolated tests
let config = ModelConfiguration(isStoredInMemoryOnly: true)
container = try ModelContainer(for: YourModel.self, configurations: config)
context = container.mainContext
}
override func tearDown() async throws {
container = nil
context = nil
try await super.tearDown()
}
}2. Swift 6 Actor Testing
@MainActor
final class ServiceTests: XCTestCase {
var service: YourActor!
override func setUp() async throws {
try await super.setUp()
service = YourActor()
}
func testActorMethod() async throws {
// Actor-isolated tests work naturally with async
let result = try await service.method()
XCTAssertEqual(result, expected)
}
}3. Given-When-Then Pattern
func testFeature() async throws {
// Given: Set up initial state
let task = service.createTask(title: "Test")
// When: Perform action
task.complete()
// Then: Verify result
XCTAssertTrue(task.isCompleted)
}4. Test Organization
@MainActor
final class FeatureTests: XCTestCase {
// MARK: - Properties
// Test dependencies
// MARK: - Setup & Teardown
// setUp/tearDown methods
// MARK: - Unit Tests
// Isolated tests
// MARK: - Integration Tests
// Tests across components
// MARK: - Edge Cases
// Boundary and error conditions
// MARK: - Performance Tests
// Performance benchmarks
}Testing Guidelines
SwiftData Models
- Always use
ModelConfiguration(isStoredInMemoryOnly: true) - Mark test classes with
@MainActor - Use
try context.save()after mutations - Verify state with
FetchDescriptorand#Predicate
Actors & Concurrency
- Test classes interacting with actors should be
@MainActor - Use
awaitfor all actor methods - Test isolation boundaries with
nonisolatedtests where appropriate
SwiftData Services
- Use in-memory mode:
YourService(inMemory: true) - Test fetch, create, update, delete operations
- Verify
FetchDescriptorqueries with predicates
EventKit Mocking
- Mock
EKEventStorefor isolated testing - Test permission handling scenarios
- Verify
EKReminderto model mapping
SwiftUI Views
- Use
@Testable importto access internal types - Test
@ObservableViewModel behavior - Test state transitions and side effects
Best Practices
- Isolation: Each test should be independent
- Async-Safety: Use
async/awaitfor all async operations - MainActor: Mark SwiftData tests with
@MainActor - Performance: Use
measureblocks for critical paths - Readability: Use Given-When-Then comments
- Organization: Group tests with
// MARK:sections
Performance Testing
func testPerformance() async throws {
measure {
// Code to measure
_ = service.process(data: largeDataSet)
}
}Common Test Patterns
Batch Query Testing
func testBatchFetchEfficiency() async throws {
let ids = (0..<100).map { "ID-\($0)" }
let start = Date()
let results = service.fetch(by: ids)
let duration = Date().timeIntervalSince(start)
XCTAssertEqual(results.count, 100)
XCTAssertLessThan(duration, 0.5, "Batch fetch should be fast")
}Predicate Testing
func testPredicateFiltering() async throws {
let descriptor = FetchDescriptor<IdentityMap>(
predicate: #Predicate { $0.isDirty == true }
)
let results = try context.fetch(descriptor)
XCTAssertEqual(results.count, expectedCount)
}Running Tests
# Run all tests
xcodebuild test -scheme YourApp -destination 'platform=macOS'
# Run specific test
xcodebuild test -scheme YourApp -destination 'platform=macOS' \
-only-testing:'YourAppTests/FeatureTests/testMethod'
# Run with performance output
xcodebuild test -scheme YourApp -destination 'platform=macOS' \
-resultBundlePath ~/TestResults.xcresult