.agents/skills/swift-testing-expert/references/migration-from-xctest.md
Use this file for incremental migration of existing XCTest code to Swift Testing while preserving safety and CI signal.
XCTest and Testing during migration.XCUIApplication)XCTMetric)import XCTest
import Testing
#expect / #require.test... naming constraints with explicit @Test.// Before (XCTest)
final class PriceTests: XCTestCase {
func testDiscountedTotal() {
XCTAssertEqual(Price.total(subtotal: 20, discount: 5), 15)
}
}
// After (Swift Testing)
import Testing
@Test func discountedTotal() {
#expect(Price.total(subtotal: 20, discount: 5) == 15)
}
XCTAssert* variants -> #expect(...).try #require(optionalValue).#require instead of global continueAfterFailure = false.XCTFail("...") -> Issue.record("...").// XCTAssertTrue(isEnabled)
#expect(isEnabled)
// XCTAssertNil(error)
#expect(error == nil)
// XCTAssertThrowsError(try run())
#expect(throws: (any Error).self) { try run() }
// try XCTUnwrap(user)
let user = try #require(user)
XCTestCase.setUp patterns to suite init when appropriate.deinit when using class/actor suites.@MainActor).import Testing
struct SessionTests {
let session: Session
init() {
self.session = Session(environment: .test)
}
@Test func startsDisconnected() {
#expect(session.isConnected == false)
}
}
await directly for async APIs.withCheckedContinuation/withCheckedThrowingContinuation.XCTestExpectation patterns with confirmations when testing asynchronous event streams.import Testing
@Test func receivesAtLeastOneEvent() async {
await confirmation("Receives event", expectedCount: 1...) { confirm in
confirm()
}
}
continueAfterFailure patterns instead of targeted #require.@MainActor unnecessarily.