| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- 자동화 테스트
- push notification
- java
- XCUITest
- XCode Console
- 포그라운드
- iOS Class Chain
- foreground
- Appium Inspector
- xpath
- XCUIElementStaticText
- 푸시알림
- WDA
- Web Driver Agent
- appium
- IOS
- Today
- Total
성장기의 히동
[Appium] 화면에서 요소를 찾지 못하는 에러, An element could not be located on the page using the given search parameters 본문
[Appium] 화면에서 요소를 찾지 못하는 에러, An element could not be located on the page using the given search parameters
용히동 2025. 9. 12. 18:12(시간이 없으시면 맨 마지막에 결론 부분을 보시면 됩니다요)
지인이 만든 앱 테스트를 진행하면서, accessibility id가 없는 경우가 많아 iOS Class Chain이나 iOS Predicate String을 활용해야 할 경우가 많았다.
어김없이 iOS Class Chain을 통해 요소를 찾고 자동화 테스트 코드를 작성하던 도중, 화면에서 요소를 찾지 못하는 에러를 맞닥뜨렸다.
에러를 맞닥뜨린 상황은 아래와 같다.
1. 알람 선택기는 총 두 개가 있고, 첫 번째 알람 선택기에서 "없음"을 선택해야 함
2. 알람 설정 TC의 테스트 자동화를 위해 아래와 같이 자바 코드를 작성함
3. Appium Inspector 상에 표시된 iOS Class Chain 값을 사용했음에도 불구하고, 화면에서 요소를 찾지 못하는 에러 발생
💭 에러 발생 상황
1. 알람 선택기는 총 두 개가 있고, 첫 번째 알람 선택기에서 "없음"을 선택해야 함
없음의 iOS Class Chain은 Appium Inspector에서 보다시피 **/XCUIElementTypeButton[`name == "없음"`][2] 이다.
(아래 사진의 우측에서 확인할 수 있다.)

2. 알람 설정 TC의 자동화 테스트를 위해 아래와 같이 자바 코드를 작성함
첫 번째 알람 선택기에서 "없음"을 찾아서 선택하기 위해, 아래와 같이 코드를 작성했다.
에러가 발생하는 부분은, 아래에서 두 번째 줄인 firstAlarm을 찾는 findElement 메서드이다.
secondAlarmSelector부터 건드리는게 마음에 안 들긴 하지만, 나름의 이유가 있다.
** 첫 번째 알람을 "없음" 으로 설정하게 되면, 알람을 켠게 사라지기 때문에 두 번째 알람부터 설정하고, 첫 번째 알람을 없음으로 설정했다.
** 과거에 테스트 자동화를 진행하기 전, 이 방식으로 두 번째에 등록한 알람이 사라지는 버그를 발견했기 때문에 같은 상황으로 테스트 자동화를 진행했다.
** 현재는 버그가 사라진 상태라서 두 번째에 등록한 알람이 첫 번째 알람으로 등록되는 UI상의 처리가 있어야 한다.
alarm = driver.findElement(iOSClassChain("**/XCUIElementTypeButton[`name == \"알람\"`]"));
alarm.click();
firstAlarmSelector = driver.findElement(iOSClassChain("**/XCUIElementTypeButton[`name == \"시작 시간에\"`]"));
secondAlarmSelector = driver.findElement(iOSClassChain("**/XCUIElementTypeButton[`name == \"없음\"`]"));
secondAlarmSelector.click();
WebElement secondAlarm = driver.findElement(accessibilityId("5분 전"));
secondAlarm.click();
firstAlarmSelector.click();
WebElement firstAlarm = driver.findElement(xpath("(//XCUIElementTypeButton[@name=\"없음\"])[2]"));
firstAlarm.click();
3. Appium Inspector 상에 표시된 iOS Class Chain 값을 사용했음에도 불구하고, 화면에서 요소를 찾지 못하는 에러 발생

에러 로그는 화면에서 해당 요소를 찾지 못하고 있다고 했다.
💭 에러 원인 분석
실제 앱 동작을 하면서 순서대로 알맞게 진행하고 있었기 때문에 에러 원인을 아래와 같이 분석했다.
1. 첫 번째 알람 선택기가 제대로 선택된 상황인가? ⭕️
- 만약 알람 선택기가 제대로 선택되지 않아 클릭 되지 않는 상황이었다면, 화면에서 해당 요소를 찾지 못하는 것이 당연하기 때문
-> 하지만 제대로 찾아서 클릭된 상황이었다. 그러니까 해당 화면에서 저 "없음" 버튼을 찾지 못하는게 이상했다.
2. iOS Class Chain에 오타가 있는가? ❌
- 오타가 있다면 당연히 찾지 못하기 때문
-> Appium Inspector에서 그대로 따온 거라서 오타가 있는게 상식적으로 말이 안 됐다.
3. Xpath로는 요소를 찾을 수 있는가? ❌
- Xpath로도 요소를 찾을 수 없다. 그렇다면 그냥 저 값이 틀렸다는 것 같다.
4. 테스트 중 해당 요소의 로케이터가 변경되는가? ‼️ 원인 발견 ‼️
- 없음 이라는 요소의 로케이터를 확인한 시점은 두 번째 알람을 변경하지 않은 상태였다.
- 그러니까 첫 번째 알람 선택기를 클릭하고, 없음 이라는 요소의 로케이터를 확인한 것이다.
- 한 번도 겪어보지 못한 상황이라, 한 번 테스트 해봤는데 실제로 로케이터가 변경되는 것을 확인했다.
- 아래에서 그 과정을 풀어보겠다.
💭 테스트 중 해당 요소의 로케이터가 변경되는 상황 분석 및 테스트 - 실제 원인
첫 번째에 업로드 한 Appium Inspector의 캡쳐다.
iOS Class Chain
**/XCUIElementTypeButton[`name == \"없음\"`][2]
Xpath
(//XCUIElementTypeButton[@name=\"없음\"])[2]

잘 보면, 내가 작성한 테스트 시나리오와 다른 점이 있다.
✨ 테스트 시나리오
1. 두 번째 알람을 5분 전으로 설정
2. 첫 번째 알람을 없음 으로 설정
✨ Appium Inspector 상황
1. 첫 번째 알람 선택기 클릭해서 "없음" 요소의 로케이터 확인
2. 두 번째 알람은 "없음" 상태
작성한 테스트 시나리오와 다른 상황에 로케이터를 확인했기 때문에, 테스트 시나리오와 동일한 과정으로 진행하며 로케이터를 다시 확인했다.
테스트 시나리오와 동일하게 진행하며 확인한 Appium Inspector의 캡쳐다.
- iOS Class Chain
**/XCUIElementTypeButton[`name == "없음"`]
- Xpath
//XCUIElementTypeButton[@name="없음"]

로케이터의 값이 변경된 것을 확인할 수 있다. 비교하기 쉽게 아래에 다시 적어봤다.
- iOS Class Chain
**/XCUIElementTypeButton[`name == \"없음\"`][2]
**/XCUIElementTypeButton[`name == "없음"`]
- Xpath
(//XCUIElementTypeButton[@name=\"없음\"])[2]
//XCUIElementTypeButton[@name="없음"]
🤞🏻 이를 바탕으로 iOS Class Chain 값을 변경해 코드를 수정했고, 테스트는 정상적으로 동작했다.
❤️ 에러 분석 결과 정리 / 결론
💭 실패 원인 - 테스트 시나리오를 따라 로케이터를 확인하지 않았다.
- 드롭다운 메뉴를 열면 UI 계층 구조가 바뀐다.
- 테스트 시나리오상 두 번째 알람을 먼저 변경하고, 첫 번째 알람을 변경해야 했는데 테스트 시나리오대로 진행하면서 로케이터를 확인하지 않았다.
- 이벤트 생성 초기 화면에서 로케이터 값을 확인하고, 그 값을 사용했다.
- 요소의 accessibility id와 같은 고유 값은 변하지 않으므로 Xpath나 iOS Class Chain도 비슷하게 생각했기 때문이다.
- 테스트 시나리오에서 UI 계층 구조 변경이 이뤄지면서, 각 요소의 로케이터 값도 변경됨을 인지하지 못했다.
결론적으로, 화면에 없는 요소를 찾으려고 했던게 맞았다.
UI 계층 구조 변경으로 로케이터 값이 변경됐는데, 이전 UI 상태의 로케이터 값으로 해당 요소를 찾으려고 했기 때문이다.
accessibility id와 달리, Xpath와 iOS class chain은 UI 구조 변경에 따라 값의 변경이 이뤄질 수 있다는 글을 작성한 적이 있다.
작성하면서 UI 구조 변경은 실제로 코드 변경이 이뤄질 때를 생각했는데, 테스트를 진행하면서 시나리오의 순서에 따라 UI 계층 구조가 달라질 수 있음을 배웠다.
만약 비슷한 문제를 겪고 있다면, 본인이 생각한 시나리오의 순서대로 진행했는지 먼저 확인해보길 바란다!
시나리오와 상이한 순서로 진행했다면, 실제로 일어날 UI 계층 구조의 변화를 캐치하지 못해 오류가 발생하고 있을 수 있다.
'☁️ QA' 카테고리의 다른 글
| [Appium, iOS] 같은 로케이터를 사용하는 버튼을 눌렀을 때, 요소를 찾지 못한다는 에러가 발생하는 이유 (0) | 2025.10.17 |
|---|---|
| [Appium, iOS] TypePickerWheel을 조작할 때 발생한 에러 직면기 및 Locator 리팩토링 (0) | 2025.10.15 |
| [QA/TC] 앱 테스트 중 기능 및 UI 변경 반영 TC 추가 및 변경 (2) | 2025.09.26 |
| [Appium] 같은 계층에 속해있으면서 같은 조건을 만족하는 StaticText를 어떻게 구분해낼 수 있을까? (1) | 2025.09.22 |
| [Appium, iOS 기준] Appium, Appium Inspector, WDA란? 왜 설치할 게 이렇게 많은가? (4) | 2025.09.06 |