apple/XCTest

[XCTest] XCTest에 대해서 알아보기 1편

lgvv 2022. 7. 3. 15:41

XCTest에 대해서 알아보기 1편

 

 

XCTest를 공식문서를 통해 정리

Nimble Quick 등도 다시볼겸 정리해보자.

사이드 프로젝트에서 테스트코드 작성하면서 점차 더 다양한 테스트를 시도하고 있는데, 정리가 한번 필요할 것 같았음

 

유닛테스트는 여러 형태로 자주 사용하고 있고,

UI테스트는 아직까지 다채롭게 사용하지는 못하는 것 같은데, 자동 완성 기능이 꽤나 쏠쏠해서 특정 플로우에 QA용으로 빠르게 작성해서 테스트 용으로 사용 중임.

 

퍼포먼스 테스트는 해본 적은 없지만 인스트루먼트 보면서 그냥 거기서 hang걸리거나 부족한 부분 없는지 체크중인데, 성능 최적화 부분에 대해서 컴파일러 최적화 등에 의존하지 않고, 직접 사용하고자 할 경우 특정 핫스팟을 발견해서 작성이 필요하다고는 알고 있음.

 

 

✅ 공식문서 

https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods

 

Apple Developer Documentation

 

developer.apple.com

 

테스트 대상에 테스트 사례 및 테스트 방법을 추가하여 코드가 예상대로 작동하는지 확인합니다.

 

 

 

 

✅ 공식문서의 Topics를 보면 XCTestCase와 XCTest로 나뉘는데, XCTest부터 알아보자.

XCTest

 

 

프로퍼티들도 있지만 자주 보이는 Setting Up and Tearing Down 위주로 알아보자.

 

Setting Up and Tearing Down

 

 - setUp(completion: (Error?) -> Void)

: 테스트 케이스 내에서 각각의 테스트가 불리기 전에 상태를 비동기적으로 리셋하고, 오류를 던질 수 있게끔 제공

 - setUpWithError()

: 테스트 케이스 내에서 각각의 테스트가 불리기 전에 리셋하고, 오류를 던질 수 있게끔 제공

- setUp()

: 테스트 케이스 내에서 각각의 상태 리셋 제공

- tearDown(completion: (Error?) -> Void)

: 각각의 테스트 케이스 종료 후에 클린업 비동기적으로 수행하고 오류 던지게끔 제공

- tearDownWithError()

: 각각의 테스트 케이스 종료 후에 클린업 수행하고 오류 던지게끔 제공

- tearDown()

: 각각의 테스트 케이스 종료 후 클린업 수행

 

 

간단히 말해서 setUp은 테스트가 수행되기 전 오직 1번, tearDown은 각각의 테스트가 종료된 후에 오직 1번 호출되는 메소드들

 

 

 

✅ 다음은 XCTestCase에 대해서 알아보자.

XCTestCase는 XCTest를 상속받고 있다.

 

OverView를 요약하자면 test의 method와 관련된 것들이 들어있으며, 퍼포먼스 테스트 등을 진행할 수 있다.

 

Managing Test Case Execution

 

- runsForEachTargetApplicationUIConfiguration: Bool

: 앱에서 설정가능한 조합에 대해 UI테스트를 실행할지 여부, 기본값은 false이다. 아직 사용해 본 적 없어서 잘 모르겠으나

Appearance(ex. 다크모드 라이트모드)

Orientation(ex. 가로 세로)

Localization(ex. en_US, zh_CN) emd

테스트 시스템은 지원되는 설정의 가능한 모든 조합을 포함하는 구성 집합을 계산하고 XCUIApplication launch()를 호출하면 테스트 반복에 각 구성을 제공한다고 한다.

예상으로는 UITest에서 설정 옵션에 대해서 테스트를 하는 것 같다!

- continueAfterFailure: Bool

: 실패가 발생한 후에도 계속 진행할 지 말지를 결정하는 메소드 true경우 계속 진행.

- excutionTimeAllowance: TimeInterval

: 시간 초과 오류로 인해 테스트가 실패하기 전 가장 가까운 minute로 반올림 된 시간(second)

테스트 시간이 이 값을 초과하면 실패로 기록함. 기본값은 600초(10분)으로 이 속성을 이용하여 장기간 실행을 방지함.

 
 

✅ Creating Asynchronous Test Expectations

비동기 테스트에서 주로 사용

 

- func expectation(description: String) -> XCTestExpectation

: 새로운 expectation을 만듭니다. parameter를 넣어주면 실패 시 해당 설명이 로그로 나타남.

 

해당 비동기 작업이 성공이라면 fulfill을 호출하여 성공임을 알려줌.

 

위의 코드처럼 아직까지는 저렇게 사용하는데, 다른 케이스를 사용할 일이 없었어서 나중에 다른 것들을 사용한다면 집중적으로 보자.

 

 

✅ Waiting for Expectations

비동기 테스트가 fulfill할 때까지 기다린다.

- func wait(for: [XCTestExpectation], timeout: TimeInterval)

: 테스트가 지정된 시간 내에 기대치를 충족할 때까지 기다립니다.

 

wait도 이정도로 간단히 사용하는데, 나중에 더 필요함을 느끼면 확장

 

✅ 테스트 코드 예시

func test_signIn() throws {
        let email = "mock1024@gmail.com"
        let password = "12a4!g"
        
        let expectation = XCTestExpectation()
        expectation.expectedFulfillmentCount = 1

        apiClient?.signIn(email: email, password: password) { result in
            switch result {
            case .success:
                XCTAssert(true)
            case .failure(let error):
                if let error = error as? APIClient.APIError {
                    XCTFail(error.localizedDescription)
                } else {
                    XCTFail(error.localizedDescription)
                }
            }
            expectation.fulfill()
        }

        wait(for: [expectation], timeout: 30)
    }

expectedFulfillmentCount: 해당 이벤트가 한번만 발생해야 한다는 의미, 만약 2번 발생하면 fail

 

🚨 내가 자주하는 실수

LLDB

 

테스트 코드 작성할 때 urlRequest를 po urlRequest를 통해 까보는데도 문제가 없다.

근데 늘 테스트 코드에서 문제가 발생하는데, 그 이유는 바로 wait 작성을 자꾸 까먹는다..

또한 requestHandler를 작성하지 않는 실수도 자주 범한다. 주의주의!

 

 

 

(참고)

https://blog.banksalad.com/tech/test-in-banksalad-ios-1/

 

뱅크샐러드 iOS팀이 숨쉬듯이 테스트코드 짜는 방식 1편 - 통합 UI테스트 | 뱅크샐러드

안녕하세요! 뱅크샐러드에서 iOS…

blog.banksalad.com