Testing
45.1 Swift Testing (Swift 6 / Xcode 16+)
Features: parameterized tests, traits (.enabled(if:), .serialized, .tags, .timeLimit), parallel execution by default, confirmation() for event expectations, an init/deinit setup/teardown, exit tests (6.2), and attachments (6.2).
import Testing
@testable import WeatherKit
@Suite("Temperature conversion")
struct TemperatureTests {
@Test func freezingPoint() {
#expect(Temperature(celsius: 0).fahrenheit == 32)
}
@Test("Converts known values", arguments: [
(0.0, 32.0), (100.0, 212.0), (-40.0, -40.0),
])
func conversion(celsius: Double, fahrenheit: Double) {
#expect(Temperature(celsius: celsius).fahrenheit == fahrenheit)
}
@Test func parsingFailsForGarbage() throws {
#expect(throws: ParseError.self) { try Temperature(parsing: "abc") }
let value = try #require(Temperature(text: "21.5")) // unwrap or fail the test
#expect(value.celsius == 21.5)
}
@Test(.disabled("Flaky on CI"), .tags(.network))
func networkFetch() async throws {
let forecast = try await WeatherService().forecast(for: "Pune")
#expect(!forecast.days.isEmpty)
}
@Test(.timeLimit(.minutes(1)), .bug("https://github.com/org/repo/issues/42"))
func longRunning() async {}
}
extension Tag { @Tag static var network: Self }45.2 XCTest (Classic)
UI testing: XCUITest (XCUIApplication, accessibility identifiers). Snapshot testing: swift-snapshot-testing (Point-Free). Mocking via protocols plus test doubles. Code coverage in Xcode (or swift test --enable-code-coverage).
Testability patterns: dependency injection through protocols, @testable import, avoiding singletons, the Clock protocol for time (TestClock), injecting URLProtocol mocks for networking.
import XCTest
@testable import WeatherKit
final class ParserTests: XCTestCase {
var parser: Parser!
override func setUp() { parser = Parser() }
override func tearDown() { parser = nil }
func testParsesTemperature() throws {
let result = try parser.parse("28C")
XCTAssertEqual(result.celsius, 28, accuracy: 0.001)
}
func testThrowsOnEmpty() {
XCTAssertThrowsError(try parser.parse("")) { error in
XCTAssertEqual(error as? ParseError, .empty)
}
}
func testAsync() async throws {
let value = try await parser.parseRemote()
XCTAssertNotNil(value)
}
func testPerformance() {
measure { _ = (0..<10_000).map { $0 * 2 } }
}
}