Unit test
Swift에서는 XCTest라는 기본 도구를 제공하기 때문에 빠르게 유닛 테스트를 할 수 있습니다.
유닛 테스트의 목적과 장점
1.유닛 테스트는 개별 함수나 메서드가 의도대로 동작하는지 확인하는 역할을 가지고 있습니다.
코드의 정확성과 안정성을 확보 할 수 있습니다.
2.코드베이스에 변경이 생기면 유닛테스트를 통하여 기존 기능이 정상 작동하는지를 빠르게 확인 할 수 있습니다.
3.테스트가 실패했을 때 오류 발생 지점을 쉽게 알 수 있기 때문에 디버깅이 쉬워집니다.
4.코드 리팩토링시 안정성을 가지게 됩니다.
프로젝트 생성시 유닛 테스트 포함
위의 사진을 보면 "Testing System 옵션 항목에 " Swift Testing with XCTest UI Tests" 가 선택되어 있습니다.
해당 옵션은 자동으로 XCTest 기반의 유닛 테스트 타깃과 테스트 파일을 프로젝트에 포함하는 옵션 입니다.
기존 프로젝트에 테스트 타깃 추가방법
Xcode 상단 메뉴에서 File->New->Target... 을 선택합니다.
프로젝트에 테스트 타깃과 기본 테스트 파일이 생성된 것을 확인할 수 있습니다.
프로젝트에 테스트 타깃과 기본 테스트 파일이 생성된 것을 확인할 수 있습니다.
유닛 테스트 클래스 작성해보기
기본 테스트 파일을 열어보게 되면
import Testing
struct voiceMemoTests {
@Test func example() async throws {
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
}
}
위의 소스코드가 기본적으로 생성된 것을 확인할 수 있습니다.
하지만 위의 코드에서 Testing 이라는 모듈과 @Test라는 에노테이션은
일반적으로 Swift의 유닛테스트에서 사용하는 XCTest와는 다릅니다.
@Test 에노테이션은 XCTest에서는 기본적으로 사용되지 않습니다.
import XCTest
@testable import voiceMemo
class VoiceMemoTests: XCTestCase {
override func setUpWithError() throws {
}
override func tearDownWithError() throws {
}
func testExample() async throws {
let value = 2 + 2
XCTAssertEqual(value, 4, "2 더하기 2는 4여야 합니다.")
}
}
XCTest에서는 보통 해당 소스코드가 많이 사용됩니다.
private struct MemoContentInputView: View {
@ObservedObject private var memoViewModel: MemoViewModel
fileprivate init(memoViewModel: MemoViewModel){
self.memoViewModel = memoViewModel
}
fileprivate var body: some View {
ZStack(alignment: .topLeading) {
TextEditor(text: $memoViewModel.memo.content)
.font(.system(size: 20))
if memoViewModel.memo.content.isEmpty {
Text("메모를 입력하세요")
.font(.system(size: 16))
.foregroundColor(.customGray1)
.allowsHitTesting(false)
.padding(.top, 10)
.padding(.leading,5)
}
}
.padding(.horizontal, 20)
}
}
해당 예제를 한번 테스트 해 보겠습니다.
import XCTest
class MemoContentInputViewUITests: XCTestCase {
var app: XCUIApplication!
override func setUpWithError() throws {
continueAfterFailure = false
app = XCUIApplication()
app.launch()
}
override func tearDownWithError() throws {
app = nil
}
func testMemoContentInputViewPlaceholder() throws {
let memoContentTextView = app.textViews["메모를 입력하세요"]
XCTAssertTrue(memoContentTextView.exists, "플레이스홀더가 표시되지 않았습니다.")
}
func testMemoContentInputViewTyping() throws {
let memoContentTextView = app.textViews["메모를 입력하세요"]
XCTAssertTrue(memoContentTextView.exists, "메모 입력 필드가 존재해야 합니다.")
memoContentTextView.tap()
memoContentTextView.typeText("Test Memo Content")
XCTAssertEqual(memoContentTextView.value as? String, "Test Memo Content", "입력된 텍스트가 올바르게 표시되지 않았습니다.")
}
}
라고 적어보겠습니다.
소스코드를 보면 다이아몬드 버튼이 있습니다.
해당 버튼을 누르면 해당부분이 빌드가 되게 됩니다.