목차
- 통합 UI 테스트는 어떤 것을 테스트 해야하는 지?
- 테스트코드 짜는 법
1. 통합 UI 테스트는 어떤 것을 테스트 해야하는 지?
- 중요한 사용자의 작업이 앱에서 완료 될 수 있는지
- UI 컨트롤의 동작이 잘 되는 지
애플에서는 위와 같은 것들을 확인하기 위해 UI 테스트를 작성한다고 해요. (전부 테스트 하라는 거 아닌가..?)
UI 테스트로 모든 로직을 테스트 하는것은 불가능해요. 왜냐하면 UI를 실제로 조작하는 테스트라서
그 안에 돌아가는 네트워크 로직이라던가 네트워크 지연이라던가 다양한 변수에서 문제가 생겼을 때 어디가 문제인지 정확하게 파악하지 못하기 때문이에요.
그래서 QA팀이 있다면 넘겨주기전에 기본적인 것들을 확인하는 용으로 UI 테스트를 작성하면 좋을 것 같아요.
또한 애플에서 말했다시피 이건 반드시 확인하고 가야한다! 라는 중요한 작업들을 UI 테스트 작성해주면 안정적인 서비스가 될 수 있어요.
로컬에서만 테스트 해볼수도 있고 자동화하여 특정 시간마다 테스트를 동작시키는 것도 할 수 있어요.
2. 테스트코드 짜는 법
- Record UI Test
기기(시뮬 or 테스트기기)에서 한 행동을 테스트함수에 코드로 적어주는 기능
위의 동영상에 나오는 코드
// 첫번째 위 텍스트필드
app.textFields["idTextField"].tap()
let aKey = app.keys["a"]
aKey.tap()
aKey.tap()
let sKey = app.keyboards.keys["s"]
sKey.tap()
sKey.tap()
let dKey = app.keys["d"]
dKey.tap()
dKey.tap()
let fKey = app.keys["f"]
fKey.tap()
fKey.tap()
// 두번째 텍스트 필드
app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .textField).element(boundBy: 1).tap()
let qKey = app.keys["q"]
qKey.tap()
qKey.tap()
let wKey = app.keys["w"]
wKey.tap()
wKey.tap()
let eKey = app.keys["e"]
eKey.tap()
eKey.tap()
let rKey = app.keys["r"]
rKey.tap()
rKey.tap()
// 로그인 버튼
app.staticTexts["로그인"].tap()
app.alerts["AlertDialog"].scrollViews.otherElements.buttons["OK"].tap()
텍스트필드 누르고 나오는 키보드를 한번씩 눌렀는데 2번씩 찍히네요??
record 한 것을 그냥 사용하는 건 무리가 있어보여요. 코드를 조금 수정하거나 직접 작성해줄게요.
그럴려면 우선 위의 코드가 어떻게 작성 되고 어떤 방식으로 작동 되는 지 알아야 코드를 작성할 수 있겠죠!?
3분 27초를 보면
Accessibility is the technology on our platforms,
that gives disabled people the same great experience on our devices
and with our applications that all other users receive.
To make Accessibility work,
it offers a rich set of semantic data
about the UI that technologies like Voice Over can use to guide users through the application.
UI testing uses that, and Accessibility is integrated with the UI kit,
and app kit, so, when you use controls from those frameworks,
you get a lot of accessibility support for free, right out of the box.
Accessibility는 보통 유저들이 받는 좋은 유저 경험을 장애인들에게도 제공할 수 있는 기술이다.
Accessibility를 동작시키기 위해서 보이스 오버(Voice Over)와 같은 기술이 사용자에게 응용 프로그램을 안내하는 데 사용할 수 있는 UI에 대한 풍부한 의미 데이터 세트를 제공한다.
UI testing은 이를 이용하며, Accessibility은 UI 키트 및 앱 키트와 통합되어 있으므로, 이러한 프레임워크의 컨트롤을 사용할 때 많은 Accessibility 지원을 무료로 바로 받을 수 있다.
글로만 보면 이해하기 힘들수도 있는데 저는 중간에 있는 보이스 오버(Voice Over) 이거 사용해보고 이해했어요.
10 ~ 30분 정도 투자하면 할 수 있으니까 한번 해보시는 걸 추천드립니다! (siri야~ 보이스 오버 켜줘~ 🤗)
요약하자면, Accessibility는 장애인들에게도 좋은 유저 경험을 제공할 수 있는 기술이고
UI Testing은 Accessibility을 사용한다고 합니다.
3. Accessibility 설정
위의 코드 다시 보면
// 첫번째 텍스트필드
app.textFields["idTextField"].tap()
// 두번째 텍스트 필드
app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .textField).element(boundBy: 1).tap()
두개가 같은 텍스트필드임에도 불구하고 코드가 다른데요. 첫번째가 훨씬 더 깔끔하죠?
제가 첫번째 텍스트필드는 Accessibility을 변경해줬기 때문이에요. 😁
- 스토리보드 Accessibility 변경
위의 이미지는 텍스트필드지만 로그인버튼으로 몇가지 실험을 해봤어요.
Label, Hint, Identifier 3개가 있는데 각각 작성하고 Voice Over, Record UI Test 기능을 사용해보니 다음과 같은 결과가 나왔어요.
Voice Over | Record UI Test | |
아무것도 안적어주었을 때 | '로그인'으로 읽어줌 | app.staticTexts["로그인"].tap |
Label만 '로그인라벨'로 적어주었을 때 | '로그인라벨'로 읽어줌 | app.staticTexts["로그인라벨"].tap() app.buttons["로그인라벨"].tap() 할 때마다 달랐음 |
Identifier만 'loginButton'로 적어주었을 때 | '로그인'으로 읽어줌 | app.buttons["loginButton"].tap() |
Label '로그인라벨', Identifier 'loginButton'로 적었을 때 |
'로그인라벨'로 읽어줌 | app.buttons["loginButton"].tap() |
Hint는 Label 읽은 후 덧붙여서 읽어줌 (Voice Over 써보면 바로 이해 가능!!)
결론
- 버튼에 써져있는 글이 버튼을 설명하기에 부족하다면 Voice Over를 위해 Hint를 적어줄 것
- UI Test를 작성할 때 accessibiltyLabel로 구분하지말고 accessibiltyIdentifier로 구분하면 좋을 것 같다. (그 이유는 밑에)
- accessibiltyLabel을 적게되면 실제 버튼에 써져있는 글과 Voice Over에서 읽어주는 Accessibility Label이 다를 수 있다.(ex. 다국어 처리 등) - 물론 테스트코드에서도 다국어처리를 하면 되지만 UI의 글귀가 바뀌어버리면 테스트 코드도 같이 바꿔줘야 하기 때문에 바꿀 가능성이 적은 identifier로 구분하는게 더 나아보인다.
- 코드로 설정 하는 법
여기서는 Label을 설정했는데 Identifier도 이런식으로 설정하면 돼요.
3. 신기해서 한번 만들어본 테스트코드
- 로그인 성공: 아이디(a)와 비밀번호(1234)를 입력하고 3초안에 다음화면으로 이동하는 지?
- 로그인 실패: 아이디(a)와 비밀번호(12)를 입력하고 3초안에 Error Alert가 뜨는 지?
1. 로그인 성공!
func test_success_login() throws {
let app = XCUIApplication()
let idTextField = app.textFields["idTextField"]
idTextField.tap()
let aKey = app.keys["a"]
aKey.tap()
let pwTextField = app.textFields["pwTextField"]
pwTextField.tap()
let moreKey = app.keys["more"]
moreKey.tap()
let key = app.keys["1"]
key.tap()
let key2 = app.keys["2"]
key2.tap()
let key3 = app.keys["3"]
key3.tap()
let key4 = app.keys["4"]
key4.tap()
app.buttons["loginButton"].tap()
XCTAssertTrue((app.staticTexts["secondVC"].waitForExistence(timeout: 3)))
}
2. 로그인 실패!
func test_fail_login() throws {
let app = XCUIApplication()
let idTextField = app.textFields["idTextField"]
idTextField.tap()
let aKey = app.keys["a"]
aKey.tap()
let pwTextField = app.textFields["pwTextField"]
pwTextField.tap()
let moreKey = app.keys["more"]
moreKey.tap()
let key = app.keys["1"]
key.tap()
let key2 = app.keys["2"]
key2.tap()
app.buttons["loginButton"].tap()
XCTAssertTrue((app.alerts["ErrorAlert"].waitForExistence(timeout: 3)))
let okButton = app.alerts["ErrorAlert"].buttons["OK"]
okButton.tap()
}
'테스트코드' 카테고리의 다른 글
Snapshot Testing (feat. iOS) (0) | 2023.03.26 |
---|---|
iOS 테스트 코드 시작하기 (2) | 2023.01.29 |
테스트 파일에 있는 resource 접근하기 - Swift (0) | 2021.10.25 |