Section 13/181 menit

13. Testing Lanjutan di SPM

13. Testing Lanjutan di SPM

Test Plan Configuration

swift
// Package.swift — multiple test targets dengan konfigurasi berbeda
targets: [
    .target(name: "CoreDomain"),
    
    // Unit tests — cepat, isolated
    .testTarget(
        name: "CoreDomainTests",
        dependencies: ["CoreDomain"],
        swiftSettings: [
            .define("TESTING")
        ]
    ),
    
    // Integration tests — butuh network/database
    .testTarget(
        name: "CoreDomainIntegrationTests",
        dependencies: ["CoreDomain"],
        resources: [
            .copy("Fixtures/")
        ]
    )
]

Menjalankan Tests

swift
# Run semua tests
swift test

# Run tests dengan parallel execution
swift test --parallel

# Run tests dengan filter
swift test --filter "CoreDomainTests.UserRepositoryTests/testFetchUser"

# Run tests dan generate code coverage
swift test --enable-code-coverage

# Lihat coverage report
swift package show-bin-path
# Kemudian:
llvm-cov report \
  .build/debug/CoreDomainPackageTests.xctest/Contents/MacOS/CoreDomainPackageTests \
  -instr-profile .build/debug/codecov/default.profdata \
  -ignore-filename-regex ".build/"

# Export coverage sebagai JSON
llvm-cov export \
  .build/debug/CoreDomainPackageTests.xctest/Contents/MacOS/CoreDomainPackageTests \
  -instr-profile .build/debug/codecov/default.profdata \
  -format lcov > coverage.lcov

Test dengan Fixtures dan Resources

swift
// Tests/CoreDomainTests/UserParserTests.swift
import Testing
import Foundation
@testable import CoreDomain

struct UserParserTests {
    
    // Akses fixtures via Bundle.module
    func loadFixture(named name: String) throws -> Data {
        guard let url = Bundle.module.url(forResource: name, withExtension: "json",
                                           subdirectory: "Fixtures") else {
            throw TestError.fixtureNotFound(name)
        }
        return try Data(contentsOf: url)
    }
    
    @Test func parseUserFromJSON() throws {
        let data = try loadFixture(named: "valid_user")
        let user = try JSONDecoder().decode(User.self, from: data)
        
        #expect(user.id == "user-123")
        #expect(user.email == "test@example.com")
    }
    
    @Test func handleMalformedJSON() throws {
        let data = try loadFixture(named: "malformed_user")
        
        #expect(throws: DecodingError.self) {
            try JSONDecoder().decode(User.self, from: data)
        }
    }
    
    enum TestError: Error {
        case fixtureNotFound(String)
    }
}