# Swift Testing Guide A comprehensive guide to organizing and writing tests with Apple's Swift Testing framework. **What you'll find here:** - Hierarchical test organization patterns for scaling your test suite - Naming conventions and best practices that prevent common pitfalls - Quick reference cheat sheet for daily use - Complete Swift Testing API reference **Who this is for:** Swift developers adopting Swift Testing, especially those working on complex projects with growing test suites that need clear organization and maintainability. --- ## Navigation | Guide | Purpose | When to Use | Length | |-------|---------|-------------|--------| | **[Quick Reference](quick-reference.md)** | One-page cheat sheet with copy-pasteable patterns, naming rules, and API essentials | Use while coding - Ctrl+F to find patterns instantly | 15 min skim | | **[Test Organization Guide](swift-testing-organization.md)** | In-depth guide to hierarchical test organization patterns with complete examples | Read when setting up new test suites or refactoring existing tests | 30 min read | | **[Swift Testing Reference](swift-testing-reference.md)** | Complete Apple Swift Testing API documentation | Reference when learning specific features or APIs | Lookup only | **Recommended reading order:** 1. Start with this README to understand the value proposition 2. Skim the Quick Reference to see patterns at a glance 3. Read the Test Organization Guide when implementing 4. Reference the Swift Testing API docs as needed --- ## Quick Example Here's what organized Swift tests look like using **Pattern A** (parent has "Tests" suffix): ```swift // File: UserManagerTests.swift import Testing /// Test suite for UserManager functionality. @Suite("User Manager") internal enum UserManagerTests {} ``` ```swift // File: UserManagerTests+Validation.swift import Testing extension UserManagerTests { /// Input validation tests for UserManager. @Suite("Validation Tests") internal struct Validation { // MARK: - Test Data Setup private static let validUserID = "user123" private static let emptyUserID = "" private static let tooLongUserID = String(repeating: "a", count: 1000) // MARK: - User ID Validation @Test("Validate user ID with correct format") internal func validateCorrectFormat() { let isValid = UserManager.validateUserID(Self.validUserID) #expect(isValid) } @Test("Reject empty user ID") internal func rejectEmptyUserID() { let isValid = UserManager.validateUserID(Self.emptyUserID) #expect(!isValid) } @Test("Reject user ID that is too long") internal func rejectTooLongUserID() { let isValid = UserManager.validateUserID(Self.tooLongUserID) #expect(!isValid) } } } ``` **File structure:** ``` Tests/MyLibraryTests/ └── UserManager/ ├── UserManagerTests.swift # Parent enum ├── UserManagerTests+Validation.swift # Validation category ├── UserManagerTests+Errors.swift # Error handling category └── UserManager+TestHelpers.swift # Test helpers ``` **Benefits:** - ✅ Clear hierarchy groups related tests together - ✅ Scalable - add categories without bloating files - ✅ Parallel execution - Swift Testing runs suites concurrently - ✅ Easy navigation - file structure mirrors test organization --- ## Key Concepts ### The "Tests" Suffix Rule **CRITICAL RULE**: Include "Tests" in EITHER the parent enum OR the child struct, NEVER both. **✅ CORRECT:** ``` UserManagerTests + Validation → UserManagerTests+Validation.swift UserManager + ValidationTests → UserManager+ValidationTests.swift ``` **❌ INCORRECT:** ``` UserManagerTests + ValidationTests → UserManagerTests+ValidationTests.swift (redundant!) ``` **Why this matters:** - Reduces redundancy and cognitive load - File location already indicates these are tests - Shorter names in test output and file lists - Forces consistent project-wide convention ### Pattern A vs Pattern B **Pattern A: Parent has "Tests"** - Parent: `UserManagerTests` | Children: `Basic`, `Validation`, `Errors` - **Advantages**: Matches standard test file naming, clear test hierarchy, shorter child names - File: `UserManagerTests+Validation.swift` **Pattern B: Child has "Tests"** - Parent: `UserManager` | Children: `BasicTests`, `ValidationTests`, `ErrorTests` - **Advantages**: Parent matches production type name, easy to filter test structs, clear separation - File: `UserManager+ValidationTests.swift` **Both patterns are equally valid.** Choose one and apply it consistently across your project. ### Simple vs Hierarchical Patterns **Use Simple Pattern** (single struct) when: - Type has < 10 tests - Focused, straightforward behavior - No need for multiple test categories ```swift // File: FieldValueTests.swift @Suite("Field Value") internal struct FieldValueTests { @Test("Create from string") internal func createFromString() { ... } } ``` **Use Hierarchical Pattern** (enum + extensions) when: - Type has multiple test categories (validation, errors, concurrency, etc.) - Test suite will grow over time - Different categories need different test data - You need scalable organization ```swift // File: UserManagerTests.swift @Suite("User Manager") internal enum UserManagerTests {} // File: UserManagerTests+Validation.swift extension UserManagerTests { @Suite("Validation") internal struct Validation { ... } } ``` --- ## Links & Resources ### Official Apple Documentation - [Swift Testing Documentation](https://developer.apple.com/documentation/testing) - Official framework docs - [WWDC 2023: Meet Swift Testing](https://developer.apple.com/videos/play/wwdc2023/10179/) - Introduction video - [WWDC 2024: Go further with Swift Testing](https://developer.apple.com/videos/play/wwdc2024/10195/) - Advanced features ### Related Resources - [Swift Evolution SE-0397](https://github.com/apple/swift-evolution/blob/main/proposals/0397-swift-testing.md) - Original proposal - [MistKit Example](https://github.com/brightdigit/MistKit) - Real-world usage of these patterns ### Contributing This guide documents patterns for organizing Swift tests effectively. If you have suggestions or improvements, please open an issue or pull request. ### License This guide is provided as-is for educational purposes. Code examples may be used freely in your projects.