References
Introduction
- Swift6~
- 매크로를 사용하여 더 간편하게 테스트를 작성하는 방법
@Test("Continents mentioned in videos", arguments: [
"A Beach",
"By the Lake",
"Camping in the Woods"
])
func mentionedContinents(videoName: String) async throws {
let videoLibrary = try await VideoLibrary()
let video = try #require(await videoLibrary.video(named: videoName))
#expect(video.mentionedContinents.count <= 3)
}
Building blocks

Component1 ) Test Functions
import Testing
@Test func mentionedContinents() { ... }
@Test
annotation을 가지는 함수
- async/throws일 수 있음
- global actor-isolated (
@MainActor
)일 수 있음
- 함수 이름에 test.. 가 들어가지 않는 걸 권장한다.
Component2) Expectations
#expect(video.mentionedContinents.count <= 3)
- 기존 XCTest에 존재하던 XCTAssert… 등의 여러 함수들이 #expect 하나로 간소화된다.
- 기본적으로 내부 condition이 true 인지 판단하고, false 인 경우 좀 더 자세한 설명을 보여준다.
2.1 required Expectations
try #require(session.isValid)
let method = try #require(payments.first)
false
또는 nil
(when unwrapping optional)인 경우 테스트를 즉시 종료시킨다.
- 일종의 early return
Component3) Traits

- add descriptive information about a test
- customize whether a test runs
- modify how a test behaves
4. test suit
struct
로 test를 묶으면 테스트를 그룹화하여 관리할 수 있다. navigator에도 그룹화된 형태로 표시된다.
- suits
- group related test functions and suits
@Suit
annotation을 통해 정의될 수도 있고
@Test
함수나 test suit을 포함하고 있는 타입들은 자동으로 suites가 된다.
- stored instance property를 가질 수 있다.
init
/ deinit
을 사용해서 set-up/tear-down 로직을 수행하기도 한다.
@Test
함수마다 다른 suit instance가 생성된다. → 상태가 공유되지 않는다.
Common Workflows
특정 조건일때만 테스트하기
@Test(.enabled(if: AppFeatures.isCommentingEnabled))
func videoCommenting() {
@Test(.disabled("Due to a known crash"),
.bug("example.org/bugs/1234", "Program crashes at <symbol>"))
func example() {
@Test
@available(macOS 15, *)
func usesNewAPIs() {
- 조건을 만족할 경우에만 테스트가 동작하게 할 수 있다.
- CI에서 왜 테스트가 동작하지 않았는지 확인이 가능하기 때문에 함수 내에서 guard를 쓰는 것보다 효과적이다.
테스트에 태그 추가하기
@Test(.tags(.formatting)) func rating() async throws {
#expect(video.contentRating == "G")
}
- 테스트 함수나 테스트suit에 태그를 추가할 수 있다. (테스트 suit에 있는 태그들은 하위 suit/test functions에 상속된다.)
- 네비게이터에서 groupByTag 옵션을 사용해서 해당 테스트들만 확인할 수 있고, 태그는 여러 프로젝트에서 공유될 수도 있다.
동일한 포맷의 테스트를 반복하기(parameterized test)
- 동일한 포맷의 테스트를 반복적으로 작성해야 하는 경우가 있다. 이 때 parameterized test를 이용할 수 있다.
struct VideoContinentsTests {
@Test("Number of mentioned continents", arguments: [
"A Beach",
"By the Lake",
"Camping in the Woods",
"The Rolling Hills",
"Ocean Breeze",
"Patagonia Lake",
"Scotland Coast",
"China Paddy Field",
])
func mentionedContinentCounts(videoName: String) async throws {
let videoLibrary = try await VideoLibrary()
let video = try #require(await videoLibrary.video(named: videoName))
#expect(!video.mentionedContinents.isEmpty)
#expect(video.mentionedContinents.count <= 3)
}
}
SwiftTesting and XCTests


- XCTest는 엄청 많은 expectation 함수를 갖지만 SwiftTesting은
#expect
하나로 처리 가능하다.

Migration
- 하나의 타겟에서 XCTest랑 SwiftTest가 둘 다 존재할 수 있다.

