-
Swift Testing으로 마이그레이션하기
테스트 프레임워크 상호 운용성을 활용하여 XCTest와 함께 Swift Testing을 두려움 없이 도입하는 방법을 알아보세요. 개발을 가속화하고 커버리지를 확장하는 고급 테스트 기능을 점진적으로 도입하기 위한 모범 사례와 패턴을 살펴보세요.
챕터
- 0:07 - Introduction
- 1:08 - Swift Testing basics
- 2:50 - Migration strategy
- 5:48 - Test framework interoperability
- 7:43 - Interoperability modes
- 13:02 - Common migration patterns
- 15:34 - Parameterized tests
- 18:02 - Exit tests
- 20:04 - Next steps
리소스
관련 비디오
WWDC26
WWDC24
-
비디오 검색…
안녕하세요! 저는 Jerry이고, Swift Testing 팀의 엔지니어입니다. 오늘은 XCTest에서 Swift Testing으로 더욱 쉽게 마이그레이션하는 방법을 소개합니다.
Swift Testing은 Xcode 16에서 도입되었습니다. 현대적인 테스팅 라이브러리로 표현력 있고 간결한 인터페이스로 테스트를 작성할 수 있습니다. Swift 생태계와도 잘 어울립니다. 예를 들어, Swift 동시성을 고려하여 만들어졌으며 테스트 케이스를 병렬로 실행하여 결과를 매우 빠르게 제공합니다.
먼저 Swift Testing의 기본 구성 요소를 살펴보고 XCTest의 유사한 개념과 비교해 보겠습니다. 다음으로 XCTest 프로젝트에 Swift Testing을 추가하겠습니다. 기존 코드를 재사용하는 방법도 시연합니다 테스트 프레임워크 상호 운용성 기능을 통해서요
XCTest를 사용하지 않더라도 함께 들어보세요! Swift Testing의 기능을 사용하는 방법을 소개합니다 XCTest가 닿지 못했던 곳까지 대담하게 나아가는 방법을요!
Swift Testing의 기본부터 시작해 보겠습니다.
테스트 파일 처음에 Swift Testing 프레임워크를 import하고 내부 타입에 접근하기 위해 testable import도 추가합니다. 그런 다음 새 함수를 만들고 @Test 매크로를 추가하여 테스트로 선언합니다.
Swift는 raw identifier를 지원하며 백틱으로 표시합니다. 공백과 구두점을 섞어서 긴 테스트 이름을 읽기 쉽게 만들어 줍니다. 테스트 본문에서는 #expect 매크로를 사용합니다 과일이 열대 기후에 해당한다는 기댓값을 정의하기 위해서요. 새 테스트를 만드는 데 이것으로 충분합니다! @Test와 #expect 매크로는 대부분 테스트의 핵심 구성 요소입니다. Swift Testing이 처음이거나 내용을 다시 확인하고 싶다면 "Meet Swift Testing"이 훌륭한 참고 자료입니다. 추가적인 구성 요소와 테스팅 워크플로우를 다룹니다.
#expect 매크로는 매우 유연하며 다양한 XCTest 어서션을 대체합니다. 무조건 실패를 유발하는 XCTFail을 대체하려면 대신 Issue.record를 사용하세요.
Swift Testing을 사용하면 더 적은 코드로 더 강력하고 표현력 있는 테스트를 작성할 수 있습니다. 그러나 몇 가지 시나리오에서는 XCTest를 계속 사용하세요. UI 자동화 및 성능 테스팅 API는 XCTest에서만 사용 가능하며 Objective-C 예외를 던지는 코드를 테스트할 때는 Objective-C로 작성된 XCTest를 사용해야 합니다. 이는 Swift 코드가, Swift XCTest도 포함하여, 이러한 예외를 안전하게 처리할 수 없기 때문입니다. 이제 테스트를 작성하고 싶으실 것 같네요! 그럼 Swift Testing으로 두려움 없이 마이그레이션하는 방법을 시연하겠습니다.
테스트 코드를 작은 단위로 마이그레이션하는 전략을 설명합니다.
다음으로 테스트 프레임워크 상호 운용성을 소개합니다 기존 테스트 코드를 재사용할 수 있게 해주는 강력한 도구입니다.
여러분의 마이그레이션이 원활하게 진행될 수 있도록 따라야 할 몇 가지 공통 패턴을 공유하겠습니다. 좋습니다. 마이그레이션 전략에 대해 이야기해 보겠습니다.
기존 테스트를 수정하면 작은 변경이라도 위험을 초래할 수 있습니다. 그래서 대부분의 XCTest는 그대로 두겠습니다. 준비가 되면 테스트를 몇 개씩 수정하되 가장 자주 업데이트하는 것들에 집중하겠습니다.
기존 테스트 타겟은 두 프레임워크의 테스트를 모두 포함할 수 있습니다. 따라서 새로운 테스트에는 이미 Swift Testing을 사용할 수 있지만 XCTest 클래스 내부에는 넣을 수 없습니다. 좋습니다! 마이그레이션 전략이 생겼으니 이제 실제로 적용해 보겠습니다. 동네 새들이 과일 배달을 하도록 훈련시키는 앱을 만들었습니다. 계절이 바뀌면 새들이 이동하는 것처럼 저도 Swift Testing으로 마이그레이션할 때가 된 것 같습니다.
Fruit 데이터 구조에 대한 XCTest 스위트가 있습니다. 최근에 과일에 기후 정보를 추가했지만 아직 테스트하지 않았습니다. Swift Testing을 사용하여 새 테스트를 추가하고 싶으며 파일을 벗어나지 않고도 그렇게 할 수 있습니다! 먼저 Swift Testing 프레임워크를 import하겠습니다.
그런 다음 이 파일 끝에 테스트를 추가하겠습니다.
참고로 Swift Testing은 테스트 스위트 밖에 테스트를 배치할 수 있어서 좋습니다. 테스트가 더 생기면 나중에 부모 스위트를 만들면 됩니다. Test 내비게이터를 보면 새 테스트가 이미 포함된 것을 확인할 수 있습니다. 이제 Product 메뉴로 가서 Test를 선택하겠습니다.
잘됐네요! 새 테스트가 성공적으로 실행되었습니다.
일부 테스트는 더 많은 설정이 필요합니다. 이 테스트는 과일 배열에 고유한 이름만 있는지 확인합니다. 원래 이 테스트를 작성할 때 어서션 설정에 여러 줄의 코드를 사용했습니다.
나중에 테스트를 실행했을 때 왜 실패했는지 이해하기 어려웠습니다. 이 테스트는 하나의 이야기를 전하려 했지만 코드에 묻혀버렸습니다. 그래서 이 다단계 어서션을 헬퍼 함수로 추출했습니다. 이제 무엇을, 어떻게 테스트하는지가 더 명확해졌습니다. 마지막으로 파일과 줄 번호 파라미터를 제공하여 XCTFail에 전달했습니다.
이제 Xcode는 실패를 헬퍼를 호출한 줄에 귀속합니다.
Swift Testing으로 새 테스트를 만들고 싶습니다 이 헬퍼, 궁극적으로 XCTFail도 호출하는 테스트를요. 그런데 XCTFail은 Swift Testing의 일부가 아닙니다. 바로 이때 테스트 프레임워크 상호 운용성이 도움이 됩니다! 한 테스트 프레임워크의 API를 안전하게 호출할 수 있게 해주는 기능으로 다른 프레임워크의 테스트 본문에서 사용할 수 있습니다.
상호 운용성을 고려할 때 두 가지 방향이 있습니다. XCTest API를 호출하여 Swift Testing 테스트에서 이슈를 보고할 수 있습니다. XCTFail을 감싸는 assertUnique 헬퍼를 재사용할 때 이런 일이 발생합니다. 반대 방향으로는 Swift Testing API를 호출하여 XCTest에서 이슈를 보고할 수 있습니다. 이 부분은 나중에 설명하겠습니다.
어느 경우든 크로스 프레임워크 이슈가 생성됩니다 이슈 보고 API와 호출된 테스트가 서로 다른 프레임워크에 속하게 됩니다. Xcode는 이러한 이슈를 처리하기 위해 기본으로 상호 운용성을 활성화합니다. 방법을 보여드리겠습니다.
testUniqueFruitNames에서 assertUnique 헬퍼를 호출합니다. 헬퍼는 XCTFail을 사용하여 실패를 보고합니다. 동일한 본문으로 또 다른 Swift Testing 테스트를 만들었습니다. 이 헬퍼는 동일한 실패를 보고해야 하지만 이 테스트에서는 크로스 프레임워크 이슈가 됩니다.
이 테스트를 실행한 후의 결과를 비교해 보겠습니다.
테스트가 통과되었는데 사실 실패할 거라고 생각했습니다 위의 XCTest처럼요. 테스트 실패가 좋은 신호일 수도 있습니다 헬퍼가 버그를 잘 잡고 있다는 뜻이니까요. 하지만 여기에 메시지가 있네요. 클릭해서 확인해 보겠습니다.
상호 운용성으로 인해 보라색 삼각형으로 표시된 두 개의 경고가 생성되었습니다. 이것들은 오류가 아니기 때문에 테스트는 여전히 통과합니다. 첫 번째 경고는 Lychee가 중복된 이름임을 알려주고 두 번째 경고는 XCTFail을 Swift Testing의 Issue.record로 교체하라고 안내합니다.
상호 운용성에는 다양한 모드가 있으며 크로스 프레임워크 이슈를 처리합니다. 방금 제한 모드를 설명했습니다. 이 모드에서는 XCTest의 크로스 프레임워크 이슈가 경고입니다. Xcode 27 이전에 생성된 테스트 플랜은 제한 모드를 상속합니다. 새 프로젝트의 경우 Xcode는 완전 모드를 사용합니다. 이 모드에서는 동일한 이슈가 오류로 유지됩니다.
테스트 플랜 설정에서 언제든지 모드를 변경할 수 있습니다. 테스트 실행 섹션에서 찾을 수 있습니다. 완전 모드가 테스트 결과를 어떻게 바꾸는지 알아보겠습니다. 테스트 플랜을 편집하겠습니다.
여기서 상호 운용성으로 필터링하겠습니다
그리고 모드를 완전로 변경하겠습니다.
이제 "Unique fruit names" 테스트로 돌아가서 다시 실행하겠습니다.
이제 테스트가 실패합니다. 메시지를 확인해 보겠습니다.
완전 모드는 XCTFail이 생성한 오류를 보존합니다. 마이그레이션을 안내하는 경고도 유지합니다. 완전 모드는 제한 모드보다 한 단계 위라고 생각하세요. 크로스 프레임워크 이슈를 경고에서 오류로 격상하여 놓칠 가능성을 줄여줍니다.
완전 모드보다 한 단계 위는 엄격 모드입니다. XCTest에서 발생하는 크로스 프레임워크 이슈에 대해 엄격 모드는 치명적 오류로 테스트를 즉시 중단합니다. XCTest API를 Swift Testing API로 교체할 곳을 찾는 데 도움이 됩니다. 이미 모드를 엄격으로 업데이트했습니다. 다시 테스트를 실행하겠습니다.
어! 헬퍼 함수에서 XCTFail을 호출하는 바로 그 위치에서 테스트가 중단되었습니다! 이 메시지를 확인해 보겠습니다.
다시 한번 XCTFail을 교체하라는 안내가 있습니다 하지만 이 헬퍼를 호출하는 XCTest가 아직 있다는 점을 기억해야 합니다. 그래서 상호 운용성은 Swift Testing의 크로스 프레임워크 이슈도 지원합니다. 모든 모드에서 해당 이슈는 오류로 유지됩니다. 따라서 두 프레임워크의 테스트 모두에서 Swift Testing API를 자유롭게 호출할 수 있습니다 두 프레임워크의 테스트 내에서요. XCTFail을 교체하는 데는 몇 단계만 필요합니다. 먼저 XCTest import를 Swift Testing import로 교체합니다.
그런 다음 XCTFail을 Issue.record로 교체하고 sourceLocation이 기존의 파일 및 줄 번호 파라미터를 대체합니다.
헬퍼를 업데이트한 후 모든 테스트 케이스를 다시 실행하겠습니다.
CMD+U를 사용하겠습니다 Product Test의 단축키입니다.
업데이트된 헬퍼로 새 테스트가 기존 XCTest와 함께 모두 예상대로 실패합니다. 테스트 프레임워크 상호 운용성 덕분에 XCTest API를 Swift Testing API로 교체했습니다 테스트의 의미를 바꾸지 않고서요. 아직 소개하지 않은 모드가 하나 더 있습니다. 모드를 none으로 설정하여 상호 운용성을 비활성화할 수 있습니다. 비활성화 후 Xcode는 크로스 프레임워크 이슈를 보고하지 않습니다 어느 방향으로도요 하지만 해당 이슈는 앱의 버그를 드러낼 수 있습니다. 상호 운용성을 비활성화하면 그 버그를 잡지 못합니다. 따라서 이 모드를 사용해야 한다면 일시적으로만 사용하세요. 대신 완전 또는 엄격 모드를 권장합니다. 완전 모드는 크로스 프레임워크 이슈를 오류로 유지하며 제한 모드에서 발전한 훌륭한 선택입니다. 엄격 모드는 말 그대로 엄격합니다! XCTest의 크로스 프레임워크 이슈를 완전히 방지하고 싶다면 매우 적합합니다. 상호 운용성과 다양한 모드는 Swift Package 프로젝트에서도 사용할 수 있습니다. swift-tools-version: 6.3으로 생성된 프로젝트 예시입니다 XCTest에서 크로스 프레임워크 이슈를 생성하는 테스트가 있습니다. 기본적으로 Swift 6.4 툴체인은 제한 모드를 활성화합니다.
swift test 명령으로 이 프로젝트를 실행하면 크로스 프레임워크 이슈가 경고로 보고되는 것을 확인할 수 있습니다.
완전 모드를 사용하려면 패키지를 swift-tools-version 6.4 이상으로 업데이트하세요.
툴스 버전을 올리면 이전 이슈가 이제 오류가 됩니다.
환경 변수를 사용하여 언제든지 기본 모드를 재정의할 수 있습니다: SWIFT_TESTING_XCTEST_INTEROP_MODE 값으로는 모드 이름을 소문자로 입력하세요.
마지막으로 상호 운용성은 제한된 API 집합을 지원합니다 두 테스팅 프레임워크 모두에서요. 방금 XCTFail 및 Issue.record API를 시연했습니다. XCTest에서는 다른 모든 테스트 어서션도 지원하며 Swift Testing에서는 두 가지 기댓값 매크로 모두를 지원합니다: #expect와 #require입니다. Swift Testing의 known issue API로 XCTest 어서션 실패를 known으로 표시할 수 있으며 Test.cancel은 XCTest의 테스트 케이스를 건너뛸 수 있습니다.
직접 마이그레이션을 진행하다 보면 몇 가지 공통 패턴을 만나게 될 것입니다. 그에 대처하는 몇 가지 팁을 공유하겠습니다.
첫 번째 패턴은 테스트 건너뛰기입니다. XCTest에서는 XCTSkip API를 사용하여 테스트를 건너뜁니다.
Swift Testing API로 교체하려면 Test.cancel을 사용하세요. Swift Testing으로 새 테스트를 작성하고 있다면 Test.cancel도 동일하게 작동합니다. 그런데 Swift Testing에는 트레이트가 있습니다 테스트 함수와 스위트에 첨부할 수 있는 어노테이션입니다.
테스트 활성화 로직을 테스트 본문에서 꺼내어 enabled 또는 disabled 트레이트로 처리하세요.
또 다른 공통 패턴은 실패 시 중단입니다. XCTest에서는 continueAfterFailure 속성을 false로 설정합니다. 이렇게 하면 첫 번째 실패한 어서션에서 테스트가 중단됩니다. Swift Testing API로 교체하려면 #require 매크로를 사용하세요. 실패 시 오류를 던져 테스트를 중단합니다 더 이상 continueAfterFailure를 설정할 필요가 없습니다. Swift Testing을 사용하면 어떤 기댓값이 테스트를 중단하고 어떤 것이 그렇지 않은지 선택할 수 있습니다.
자세한 내용은 개발자 문서에서 "Migrating a test from XCTest"를 확인하세요. 더 많은 시나리오를 다루고 있으며 마이그레이션 과정에서 훌륭한 참고 자료가 될 것입니다. Xcode의 Coding Assistant도 이 문서를 인식하고 있습니다. 마이그레이션 전략을 수립하거나 작업을 검토하는 데 도움이 됩니다. 마이그레이션의 일부를 자동화하는 스킬도 있습니다. 정말 많은 내용을 다뤘네요! 요약하자면, 두려움 없이 Swift Testing으로 마이그레이션하는 방법입니다.
준비가 될 때까지 XCTest를 수정해야 한다는 압박을 느끼지 마세요. Swift Testing을 사용하여 새 테스트를 작성하는 데 집중하세요. 상호 운용성에 의존하여 XCTest API를 감싸는 헬퍼 코드도 재사용할 수 있습니다.
그 과정에서 XCTest의 크로스 프레임워크 이슈를 발견하게 됩니다. 상호 운용성을 통해 XCTest API를 Swift Testing API로 교체하여 이를 해결할 수 있습니다 Xcode 27은 상호 운용성을 기본으로 활성화합니다. 앞으로 발생하는 크로스 프레임워크 이슈를 모두 처리하려면 완전 또는 엄격 모드로 업그레이드하세요.
이제 Swift Testing에 집중할 시간입니다.
Swift Testing으로 마이그레이션하면 테스트를 강화할 새로운 도구를 사용할 수 있습니다. 매개변수화 테스트부터 시작해 보겠습니다.
다양한 인수로 반복 실행되는 테스트입니다. 각 인수는 별도의 테스트 케이스가 됩니다. 매개변수화 테스트 케이스를 포함한 모든 Swift Testing 테스트는 기본적으로 병렬로 실행됩니다. 직렬 실행보다 더 빠를 수 있습니다. 이 예시를 보세요.
프로젝트의 bird 테스트를 Swift Testing으로 마이그레이션했습니다. 모든 새가 40번에서 100번까지 날갯짓을 할 수 있는지 확인합니다. 하지만 각 조합마다 별도의 테스트를 작성할 수는 없습니다 조합의 수가 너무 많으니까요. 기존 XCTest의 본문에서는 중첩 루프를 사용하여 모든 조합을 생성했습니다. 테스트를 실행해 보겠습니다.
몇 가지가 눈에 띄었습니다. 조합이 많아서인지 테스트를 완료하는 데 시간이 걸렸습니다. 또한 테스트가 실패했지만 어떤 새가 실패했는지도 모릅니다.
여전히 XCTest를 사용하고 있었다면 오류를 잡거나 디버거를 연결하여 테스트를 실행해야 했을 것입니다. 더 좋은 방법이 있습니다. 이것을 매개변수화 테스트로 만들어 보겠습니다. 테스트 본문에서 이 루프들을 제거하는 것으로 시작합니다
대신 bird와 count를 테스트 함수 파라미터로 정의합니다.
bird와 count의 입력을 테스트 매크로의 인수로 제공합니다.
Swift Testing은 첫 번째 인수의 각 bird를 두 번째의 각 count와 짝지어 줍니다. 테스트를 다시 실행하겠습니다.
이런! 이번에는 테스트가 거의 즉시 완료되었습니다 Swift Testing이 모든 조합을 병렬로 실행했기 때문입니다. Test 내비게이터에서 매개변수화 테스트의 왼쪽에 펼치기 화살표가 생겼습니다. 클릭하면 테스트 중인 모든 조합을 확인할 수 있습니다.
정말 많은 테스트 케이스네요. 그래도 실패한 조합을 찾아야 합니다. Test 내비게이터에서 실패한 테스트 결과를 필터링하겠습니다.
이제 찾았습니다! 제비는 43번 미만으로는 날갯짓을 할 수 없네요. 매개변수화 테스트를 사용하여 테스트 실행 성능이 크게 향상되었습니다. 더 빠르게 결과를 얻었을 뿐만 아니라 어떤 테스트 입력이 실패했는지 명확하게 알 수 있었습니다.
다음으로 exit test로 테스트 커버리지를 강화하는 방법을 보여드리겠습니다. exit test는 macOS, Linux, FreeBSD, Windows에서만 지원됩니다. 테스트 커버리지가 필요한 코드를 찾고 있는데 Bird 이니셜라이저에서 발견했습니다.
새 Bird의 이름이 비어 있으면 precondition 실패로 프로그램을 중단합니다.
이미 테스트했는지 확인하려면 "Editor" 메뉴로 가서 "Code Coverage"를 표시하세요.
커버리지 어노테이션은 precondition을 빨간색으로 표시합니다 어떤 테스트도 이 코드를 실행하지 않는다는 의미입니다. exit test가 이 커버리지를 추가하기에 완벽한 도구입니다.
#expect 매크로로 exit test를 정의합니다. 예상 프로세스 종료 조건을 제공하고 exit test의 본문도 작성합니다. 테스트를 시작하면 Swift Testing이 자식 프로세스에서 exit test 본문을 실행합니다. 해당 코드는 격리되어 있기 때문에 다른 테스트를 방해하지 않고 충돌이 발생할 수 있습니다. exit test는 자식 프로세스가 완료될 때까지 기다렸다가 종료 상태를 확인하여 테스트 성공 또는 실패를 결정합니다. 테스트 스위트 익스텐션에 새 테스트를 추가할 수 있습니다. #expect 매크로를 사용하여 exit test를 만들고 프로세스가 실패로 종료되어야 함을 지정합니다.
exit test 본문 안에서 빈 이름으로 Bird를 생성합니다. 충돌이 발생하겠지만 격리됩니다 Swift Testing이 이 코드를 별도의 프로세스에서 실행하기 때문입니다. 이제 모든 테스트를 실행하겠습니다.
exit test가 통과되었습니다! 커버리지를 한 번 더 확인해 보겠습니다. 오른쪽 클릭하여 Bird 이니셜라이저의 "Jump to Definition"을 선택합니다. 돌아왔으니 커버리지를 다시 확인해 보겠습니다. 이제 커버리지 어노테이션이 precondition을 초록색으로 표시합니다 이제 테스트가 되었다는 의미입니다!
테스트를 강화하는 두 가지 방법을 간략히 살펴보았습니다 Swift Testing을 개선할 아이디어가 있다면 기여를 권장합니다! Swift Testing은 오픈 소스이기 때문입니다. GitHub의 SwiftLang 조직에 포함되어 있습니다. 그 어느 때보다 더 많은 플랫폼에서 사용 가능하며 올해부터 FreeBSD를 완전히 지원합니다.
Testing Workgroup이 프로젝트를 관리합니다 Swift 커뮤니티 누구나 참여할 수 있는 정기 회의를 운영합니다. 새 기능은 Swift Evolution을 통해 발전합니다. 사실 상호 운용성도 그 중 하나입니다! Swift Forums에 참여하여 의견과 아이디어를 공유하세요. 이제 새처럼 날아올라 Swift Testing으로 마이그레이션하세요! Xcode 27의 상호 운용성이 이 전환을 그 어느 때보다 쉽게 만들어 줍니다. 프로젝트에서 직접 사용해 보고 다양한 모드를 탐색해 보세요. 그 과정에서 강력한 도구들을 활용하세요 매개변수화 테스트와 exit test처럼요. 더 깊이 탐구하려면 WWDC 2024의 "Go further with Swift Testing"을 확인하세요. 테스트 개선을 즐기세요!
-
-
1:12 - Name a test using a raw identifier
import Testing @testable import DemoApp @Test func `Default climate: tropical`() async throws { let fruit = Fruit(name: "Coconut") #expect(fruit.climate == .tropical) } -
5:03 - Wrap XCTFail in a test helper function
func testUniqueFruitNames() async throws { assertUnique(Market.fruits + [Fruit.lychee]) } // TestHelpers.swift func assertUnique(_ fruits: [Fruit], file: StaticString = #filePath, line: UInt = #line) { var uniqueNames = Set<String>() for name in fruits.map(\.name) { if !uniqueNames.insert(name).inserted { XCTFail("Duplicate name: \(name)", file: file, line: line) } } } -
10:12 - Replace XCTFail with Issue.record in the test helper
import Testing func assertUnique(_ fruits: [Fruit], sourceLocation: SourceLocation = ...) { var uniqueNames = Set<String>() for name in fruits.map(\.name) { if !uniqueNames.insert(name).inserted { Issue.record("Duplicate name: \(name)", sourceLocation: sourceLocation) } } } -
12:15 - Run Swift Package tests with the strict interoperability mode from Terminal
> SWIFT_TESTING_XCTEST_INTEROP_MODE=strict swift test -
13:10 - Common migration: skipping tests
let isFall = false // XCTest func testSwallowFallMigration() async throws { try XCTSkipIf(!isFall, "Wrong season for migration") // ... } // Test.cancel interoperability from Swift Testing func testSwallowFallMigration() async throws { if !isFall { try Test.cancel("Wrong season for migration") } // ... } // ✅ Prefer test trait in Swift Testing @Test(.enabled(if: isFall, "Wrong season for migration")) func `Swallow fall migration`() async throws { // ... } -
13:41 - Common migration: halting after test failures
func testExample() async throws { #expect(Fruit.banana.climate == .temperate) try #require(Fruit.banana == Fruit.plantain) XCTFail("This is never reached") } -
15:57 - Example of nested loops which can be converted into a parameterized @Test function
struct BirdTests { @Test func `Birds flap wings successfully`() async throws { for bird in Aviary.birds { for count in (40...100) { try await bird.flapWings(count: count) } } } } -
16:47 - Refactor nested loops into a parameterized @Test function
struct BirdTests { @Test(arguments: Aviary.birds, 40...100) func `Birds flap wings successfully`(bird: Bird, count: Int) async throws { try await bird.flapWings(count: count) } } -
18:21 - Precondition check on empty input name in an initializer
// In `Bird.init(...)` if name.isEmpty { preconditionFailure("Bird name cannot be empty") } -
19:27 - Add coverage for precondition failure with exit test
extension BirdTests { @Test func `Bird with empty name crashes`() async throws { await #expect(processExitsWith: .failure) { _ = Bird(name: "") } } }
-
-
- 0:07 - Introduction
How to fearlessly migrate from XCTest to Swift Testing using the new interoperability feature.
- 1:08 - Swift Testing basics
A quick review of core Swift Testing building blocks — the @Test macro, #expect, and how they compare to XCTest assertions.
- 2:50 - Migration strategy
Covers the recommended incremental approach: leave existing XCTests in place, and start writing new tests in Swift Testing right away.
- 5:48 - Test framework interoperability
Introduces the interoperability feature that lets you safely call XCTest or Swift Testing API from within a test belonging to the other framework.
- 7:43 - Interoperability modes
Walks through the four interoperability modes — Limited, Complete, Strict, and None — and how to configure them in Xcode Test Plans and Swift packages.
- 13:02 - Common migration patterns
Covers practical patterns you will encounter during migration, including replacing XCTSkip with Test.cancel or traits, and continueAfterFailure with #require.
- 15:34 - Parameterized tests
Shows how to replace loop-based XCTest cases with Swift Testing parameterized tests for faster parallel execution and clearer failure reporting.
- 18:02 - Exit tests
Demonstrates how to use Swift Testing exit tests to cover code paths that call preconditionFailure or crash, running them safely in a child process.
- 20:04 - Next steps
Recaps the migration path, highlights Swift Testing open-source availability and cross-platform support, and encourages community participation.