본문 링크 (Original Link)

아이폰, 아이패드를 위한 XCUITests 설계하기

2018.04.04

# • #

by Shashikant Jagtap, translated by pilgwon

image1

애플의 XCUITest 프레임워크는 iOS 앱 UI 자동화 분야에 있어서 뜨고있는 프레임워크입니다. WWDC 2015에 발표된 이래로 많은 관심과 발전이 있었습니다. XCUITest는 UI 테스트를 스위프트로 짤 수 있게 만들어져있어서 개발자들이 아이폰과 아이패드에 더 쉽게 UI 테스트를 넣을 수 있습니다. 자신의 앱이 아이패드에서 어떻게 보이는지는 아이폰 아이패드 모두에게 고려할만한 내용이라고 생각합니다. XCUITest가 있다면, 유닛과 UI 테스트가 같은 프레임워크(XCTest)로 만들어진것처럼 지속적인 통합(CI)과 지속적인 배포(CD)가 고통스럽지 않을 것입니다. XCUITest가 나오기 이전에는 Appium이나 Calabash 같은 도구들이 UI 테스트를 루비나 자바로 짜야했고 그건 iOS CI/CD에 있어서 아주 고통스러운 단계 중 하나였습니다. 하지만 XCUITest는 iOS 앱을 위해 만들어졌지만 iOS 기기는 크기가 다른 아이패드들, 크기가 다른 아이폰으로 이루어져 있습니다. 우리는 XCUITest가 어렵지 않게 모든 종류의 기기를 커버하는지 확인해야 합니다. 만약 XCUITest가 적절하게 만들어졌다면 우리는 코드를 복붙할 필요가 없을 것이고 다양한 기기에서 계속 XCUITest를 사용할 수 있을 것입니다. 이 글에선, 우리는 아이폰과 아이패드 둘 모두를 위한 XCUITest 설계하는 법에 대해 알아볼 예정입니다.

XCUITest

XCUITest가 처음이시라면 XCUITest 프레임워크의 기본적인 내용을 이해하기 전에 이 WWDC 비디오를 보고 오셔야 합니다. XCUITest는 애플 자신의 프로그래밍 언어인 스위프트로 테스트를 짤 수 있게 해줍니다. 그게 바로 Appium이나 Calabash 등과 같은 써드 파티 프레임워크와 다른 점입니다. 만약 여러분이 XCUITest와 Appium을 비교해보고 싶으시다면 이 글을 읽으시면 각 프레임워크에 대해 더 잘 이해하실 수 있을겁니다. 만약 여러분이 새로운 XCUITest의 기능에 대해 빠르게 둘러보고 싶으시다면 제 블로그의 이전 글인 XCode 9와 새로운 XCUITest의 기능들에서 자세한 예제들과 함께 거의 모든 기능들을 보실 수 있습니다. 만약 프로토콜 기반 아키텍쳐를 설정하고 싶으시면 이 글에 잘 나와있고 다음편도 여기 있습니다. 그리고 WWDC 2017 토크 온 토크에서 발표한 테스트를 위한 엔지니어링에서 언급된 것처럼 XCUITest를 확장성있게 만들 수 있습니다.

UIDevice와 XCUIDevice

애플은 현재 기기 정보를 표시해주는 UIDevice 클래스와 물리 버튼과 화면 방향을 표현하는 XCUIDevice를 만들었습니다. 이 둘은 XCUIElements를 잘 정리해두었다면 아이폰과 아이패드에서 테스트 하는 것을 아주 쉽게 만들어줍니다. UIDevice API를 사용하면, 우리는 다음과 같은 코드를 통해 실제 기기에서 테스트할 수 있게 됩니다.

if UIDevice.current.userInterfaceIdiom == .pad {
  // 아이패드에서 할 일을 입력하세요
}

XCUIDevice를 사용한 다음의 코드로 기기의 화면 방향을 가로나 세로로 변경할 수 있습니다.

XCUIDevice.shared().orientation = .landscapeRight

이 두 API들은 아이폰과 아이패드 모두에서 XCUITest를 세팅할 떄 엄청나게 유용합니다.

테스트를 둘로 나눠서 하지마세요

많은 프로젝트에서 저는 사람들이 아이폰과 아이패드를 위한 테스트 케이스를 두 가지로 나누는 것을 보았습니다. Xcode에는 아이폰과 아이패드를 나눠서 테스트 할 수 있는 스키마가 준비돼있습니다. 게다가 테스트 전체를 조건적으로 실행하면 관리하기가 쉽지 않습니다. 앞에서 말한대로 나눠서 할 필요가 없습니다. 글 뒤쪽에서는 이러한 문제들을 해결할 방법에 대해 알아볼 예정입니다.

XCUIElements 모으기

아이패드와 아이폰에서 XCUITest를 만들 때, XCUIElements를 알맞은 형태로 모으는 것은 아주 중요한 일입니다. 저는 화면에 있는 요소들을 모으는 데에 스위프트의 enumerations를 쓰는 것을 강력히 추천드립니다. XCUITest의 프로토콜 기반 아키텍쳐는 이 글을 참고하세요. 제 최근 글인 XCUIElement를 스위프트 enumeration으로 모으기에서 어떻게 모으는지에 대해 잘 적어두었으니 참고하시기 바랍니다. 여기 버튼 세 개, 두 개의 텍스트를 포함한 홈 화면을 가진 iOS 앱이 있다고 상상해봅시다. 그러면 enum은 아래와 같을 것입니다.

import XCTest
enum HomeScreen: String {
    case guestButton = "Hello"              // 버튼 1
    case registerButton = "Register"        // 버튼 2
    case loginButton = "Login"              // 버튼 3
    case welcomeText = "Welcome"            // 텍스트 1
    case introText = "Introduction to app"  // 텍스트 2
    var element: XCUIElement {
        switch self {
        case .guestButton, .registerButton, .loginButton :
            return XCUIApplication().navigationsBars["XYZ"].buttons[self.rawValue]
        case .welcomeText, .introText:
            return XCUIApplication().staticTexts[self.rawValue]
        }
    }
}

이 코드에선 enum 케이스들에 스트링 값을 할당했고 케이스들을 버튼과 텍스트로 그룹지었습니다.

아이패드에서의 조건부 XCUIElements

위에서 언급한 enum은 버튼들이 네비게이션바에 있는 아이폰의 경우엔 완벽하게 작동합니다. 하지만 만약 모든 버튼이 탭바에 있도록 디자인된 아이패드라면 어떨까요. 위의 코드처럼 접근하면 그 아이패드에선 제대로 작동하지 않을 것입니다. 그러나 UIDevice를 사용하면 아래 코드처럼 조건적으로 아이폰과 아이패드를 나눌 수 있게됩니다.

import XCTest
enum HomeScreen: String {
    case guestButton = "Hello"
    case registerButton = "Register"
    case loginButton = "Login"
    case welcomeText = "Welcome"
    case introText = "Introduction to app"
    var element: XCUIElement {
        switch self {
        case .guestButton, .registerButton, .loginButton :
             if UIDevice.current.userInterfaceIdiom == .pad {
                 return XCUIApplication().tabBars["XYZ"].buttons[self.rawValue]
             } else {
                 return XCUIApplication().navigationsBars["XYZ"].buttons[self.rawValue]
             }
        case .welcomeText, .introText:
            return XCUIApplication().staticTexts[self.rawValue]
        }
    }
}

위와 같이 하면, enum은 아이패드에선 탭바의 버튼을, 아이폰에선 네비게이션바의 버튼을 반환할 것입니다. 그리고 XCUIElements에 접근할 실제 테스트 구현은 만질 필요가 없습니다. 이러한 접근법을 사용하면 우리는 수많은 코드의 복붙을 피하면서 다양한 기기, 다양한 화면 방향에 맞는 테스트 코드를 작성할 수 있게됩니다.

결론

XCUITest의 프로토콜 기반 아키텍쳐와 스위프트 enumeration, 그리고 애플의 UIDevice API가 있다면 우리는 아이폰과 아이패드 기기에서 코드 복사 없이 UI 자동화를 이뤄낼 수 있습니다! 또 다른 스키마를 만들거나 아이패드를 시나리오를 위해서 조건문을 떡칠할 필요도 없습니다. 제가 설명드린 아이폰과 아이패드 둘 다를 위한 테스트 설계하는 방법에 대한 접근이 마음에 드셨으면 좋겠습니다. 이 접근법에 대해 어떻게 생각하시는지 또는 더 나은 방법을 저에게 알려주세요! 배우는건 정말 즐거운 일이니까요.