이전편 Unit Test를 보신후 참고하시면 좋습니다.
말 그래도 UI가 정상 동작하는가 즉
예측한 대로 동작하는가에 관한 자동화 테스트를 말함
.accessibilityIdentifier(<#T##identifier: String##String#>)
--- or ---
accessibilityIdentifier = "Identifier"
위 같은 식별자를 통해 UI가 정상 동작하는지 테스트 하는 원리
let app = XCUIApplication()
// okay button이 있는 경우 성공
XCTAssert(app.buttons["okay"].exists)
// "Hello World" 라는 문자열이 있는 경우 성공
XCTAssert(app.staticTexts["Hello World"].exists)
// 2초 내로 "TEST2" 라는 문자열이 보여지는 경우 성공
XCTAssert(app.staticTexts["TEST2"].waitForExistence(timeout: 2))
// image1 이라는 이미지가 있는 경우 성공
XCTAssert(app.images["image1"].exists, "There is no image1 image")
// 실패
XCTFail()
let app = XCUIApplication()
app.buttons["button"].tap()
app.buttons["doubleTapButton"].doubleTap()
식별자를 통해 버튼을 찾고 액션을 준다.
let pointX = app.frame.width/2
let pointY = app.frame.height/2
let pointLocation = CGVector(dx: pointX, dy: pointY)
let normalizedLocation = app.coordinate(withNormalizedOffset: CGVector(dx:0, dy: 0))
let tapLocation = normalizedLocation.withOffset(pointLocation)
tapLocation.tap()
좌표를 통해 특정 지점을 탭 해도록 한다.
import XCTest
@testable import Testable
@MainActor
final class TestableUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testTappedStartButton() {
let app = XCUIApplication()
let id = TestIdentifiers.contentViewStartButton.identifier
let startButton = app.buttons[id]
guard startButton.exists else {
XCTFail("Lost Start Button")
return
}
startButton.tap()
}
func testStartButtonExistsAndTap() {
let app = XCUIApplication()
app.launch()
let startButton = app.buttons[TestIdentifiers.contentViewStartButton.identifier]
XCTAssertTrue(startButton.waitForExistence(timeout: 3), "Start button should exist")
startButton.tap()
}
func testSumTextExists() {
let app = XCUIApplication()
app.launch()
let sumText = app.staticTexts[TestIdentifiers.contentViewSumText.identifier]
XCTAssertTrue(sumText.waitForExistence(timeout: 3), "Sum label should exist")
}
func testStartThenSumChanges() {
let app = XCUIApplication()
app.launch()
let startButton = app.buttons[TestIdentifiers.contentViewStartButton.identifier]
let sumText = app.staticTexts[TestIdentifiers.contentViewSumText.identifier]
XCTAssertTrue(startButton.waitForExistence(timeout: 3), "Start button should exist")
XCTAssertTrue(sumText.waitForExistence(timeout: 3), "Sum label should exist")
let initialValue = sumText.label
startButton.tap()
let predicate = NSPredicate { _, _ in sumText.exists && sumText.label != initialValue }
let exp = expectation(for: predicate, evaluatedWith: nil, handler: nil)
wait(for: [exp], timeout: 5.0)
XCTAssertNotEqual(sumText.label, initialValue, "Sum label should change after loading numbers")
}
}
let p = NSPredicate { _, _ in sumText.exists && sumText.label != initialValue }
참 거짓 구분위한 객체 구성
비동기 조건이 충족될 때가지 가디리는 방식
일정 시간 동안 재시도
let exp = expectation(for: predicate, evaluatedWith: nil, handler: nil)
Expection 정의
wait(for: [exp], timeout: 5.0)
5초까지 비동기(expectation) 종료를 대기
이번엔 UITest를 다루어 보았습니다.
사실 이것 외에도 더 많은 메서드나 방식이 존재하는데
그런 부분은 찾아보면서 하는게 더 맞는 방법인 것 같아
여기까지 정리 해보도록 하겠습니다.
아직 Testable 에 대해서 다루지 않아서 다시 다루긴 할 겁니다.
다음 시간은 아마
Transition Animation에 대해서 다루어 보도록 하겠습니다.
WWDC 2024 글을 참고할 예정이니 많은 관심 부탁 드립니다.