기존의 XCTest를 대체할 수 있는
새로운 테스트 "Swift Testing"
너무 궁금하다. 빨리 해보러 갑시다. ㄱㄱㄱㄱ
목차
- 환경
- Building blocks
- Common workflows
- Swift Testing and XCTest
- Open source
환경
- Xcode 16 이상에서 사용 가능!! (8/5일 기준 xcode 16 beta버전으로 블로그 작성됨)
Xcode beta 버전 다운로드 -> (https://developer.apple.com/kr/xcode/resources/)
Building blocks
1. Test functions
import Testing
struct SwiftTesting_iOSTests {
@Test func example() {
}
}
Swift Testing에서는 @Test 어노테이션을 사용하여 테스트 함수를 작성합니다.
테스트할 내부 로직을 작성 해봅시다.
2. Expectations
2-1. Regular Expectations
import Testing
@testable import SwiftTesting_iOS // SwiftTesting_iOS로 앱의 모듈 불러오기
struct SwiftTesting_iOSTests {
@Test func example() {
let viewModel = ViewModel()
#expect(viewModel.numberThree() == 3)
}
}
#expect 매크로를 이용해서 viewModel.numberThree() 함수가 3 인지 확인하는 로직을 작성할 수 있습니다.
2-2. Required Expectations
struct SwiftTesting_iOSTests {
@Test func example() async throws {
let viewModel = ViewModel()
var isNil: String? = nil
let method = try #require(isNil) // nil 이거나 false 면 다음으로 안넘어감
#expect(viewModel.numberThree() == 3) // #require nil이어서 실패하여 코드 실행 안됨
}
}
만약 #require에서 nil이거나 테스트에 실패하면 다음 라인의 코드가 실행되지 않습니다.
3. Traits (테스트 함수에 태그 달기)
위에서 적힌대로 어노테이션에 테스트 함수의 설명을 적을 수 있습니다.
실제로 실행한다면
콘솔에 설명글 잘 찍어주네요.
4. Suites (모음, 그룹화)
import Testing
@testable import SwiftTesting_iOS
struct SwiftTesting_iOSTests {
let viewModel = ViewModel()
@Test("Check test function") func example() async throws {
#expect(viewModel.numberThree() == 3)
}
@Test("Check test function 2") func example2() async throws {
#expect(viewModel.numberThree() == 2)
}
}
Struct 로 묶어서 관련된 테스트들을 모아놓을 수 있고, 위의 예시와 같이 모든 테스트 함수에서 사용되는 객체(viewModel)를 따로 빼둘수도 있습니다.
Common workflows
1. Tests with conditions
- Runtime conditions
- .enabled(if: ...) : 특정 기기나 환경에서만 테스트되어야할 때 사용.
- .disabled(...), .bug : 비활성화된 테스트를 설명하는 주석 역할로 사용. (컴파일된 내부 코드를 확인하므로 주석보다 선호됨)
- available (...) : 테스트 전체 본문을 특정 OS에서만 실행하려고 할 때 사용.
2. Tests with common characteristics
- Test tag : 공통점이 있는 테스트에 Tag로 서로 연결할 수 있음. (ex. .enabled(if: ...), .tags(...))
3. Tests with diffrrent arguments
- arguments : 인자에 따른 테스트 함수를 각각 적을 필요 없이 아래 이미지처럼 간단하게 테스트 함수 작성 가능. (각 인수를 병렬로 실행 하여 빠른 결과를 얻을 수 있음)
Swift Testing and XCTest
Test Function에서의 차이점
XCTest | Swfit Testing | |
Discovery | Name begins with "test" (테스트 함수명 test로 시작해야함) |
@Test |
Supported types | Instance methods | Instance methods Static/class methods Global function |
Supports traits (테스트 함수 설명 달기) | No | Yes |
Parallel exection (병렬 실행) | Multi process macOS and Simulator only | In-process Supports device |
Expectations에서의 차이점
Swift Testing 에서는 #expect, #require 단 두개로 XCTest의 expectations을 다 커버합니다. 👍
이게 가능한 이유는 #expect(a > b) 이런 식으로 다양한 비교 연산자를 사용할 수 있기 때문입니다.
Suites에서의 차이점
Migrating from XCTest (https://developer.apple.com/documentation/testing/migratingfromxctest)
XCTest와 Swift Testing은 단일 대상에 공존할 수 있으므로 점진적으로 마이그레이션 할 수 있습니다.
테스트 메서드가 하나만 있는 XCTest 클래스의 경우 전역 @Test 함수로 마이그레이션하는 것을 고려하세요.
XCTAssert(...)를 Swift Testing에서 호출하거나 #expect 매크로를 XCTest에서 호출하지 마세요.
### XCTest를 계속 사용해야하는 테스트(Swift Testing 지원 X)
1. XCUIApplication과 같은 UI 자동화 API
2. XCTMetric과 같은 성능 테스트 API를 사용하는 테스트
3. Objective-C로만 작성할 수 있는 모든 테스트
Open source
Swift Testing은 오픈 소스입니다.
https://github.com/swiftlang/swift-testing
정리
- 테스트 함수는 func 앞에 @어노테이션을 붙이는 것으로 생성할 수 있다.
- 테스트 함수 내에서 #expect와 #required 매크로를 사용하여 테스트하고자 하는 값을 검증할 수 있다.
- Traits을 이용하여 테스트 함수에 태그를 달 수 있다.
- 인자에 따른 테스트 함수를 각각 작성할 필요 없이 함수 1개에 여러개의 인자를 넣을 수 있다. ⭐️ ⭐️ ⭐️
이로서 Swift Testing에 대한 기본적인 설명은 된 것 같습니다. 그런데 생각해보니 비동기에 대한 테스트 처리 내용이 없네요.
비동기에 대한 테스트 방법은 Swift Testing 심화편인 Go the futher more Swift Testing : https://developer.apple.com/videos/play/wwdc2024/10195/에서 설명해주고 있습니다.
비동기 테스트는 다음 포스팅(Swift Testing 2편)에서 해보도록 하겠습니다!