AI를 활용한 셀프 힐링 Selenium 프레임워크 구축
Source: Dev.to

“셀프 힐링”이 실제 의미하는 바
- 런타임에 깨진 로케이터를 감지합니다
- 대체 전략(또는 AI 순위)을 사용하여 올바른 요소를 찾습니다
- 옵션으로 소스의 로케이터를 업데이트하여 동일한 오류가 반복되지 않도록 합니다
이는 불안정한 테스트 재시도와 다릅니다 — 증상을 억제하는 것이 아니라 근본 원인을 해결하고 있습니다.
핵심 패턴: 로케이터 폴백 체인
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
LOCATOR_STRATEGIES = [
(By.ID, "submit-btn"),
(By.CSS_SELECTOR, "button[data-testid='submit']"),
(By.XPATH, "//button[contains(text(),'Submit')]"),
(By.CSS_SELECTOR, "form button[type='submit']"),
]
def find_element_with_healing(driver):
for strategy, locator in LOCATOR_STRATEGIES:
try:
el = driver.find_element(strategy, locator)
print(f"Located using: {strategy} → {locator}")
return el
except NoSuchElementException:
continue
raise Exception("Element not found via any strategy")
각 로케이터는 우선순위 목록을 가지고 있습니다. 기본 로케이터가 실패하면 다음 전략으로 순차적으로 넘어갑니다.
AI 추가: 유사도 점수를 통한 후보 순위 매기기
똑똑한 버전은 무작정 되돌아가지 않고 페이지의 후보들을 점수화하여 가장 일치하는 항목을 선택합니다. 간단한 접근법으로 DOM 속성 유사도를 활용합니다:
from difflib import SequenceMatcher
from selenium.webdriver.common.by import By
def similarity(a, b):
return SequenceMatcher(None, a, b).ratio()
def find_best_candidate(driver, target_attributes: dict):
candidates = driver.find_elements(By.CSS_SELECTOR, "*")
best_score = 0
best_element = None
for el in candidates:
score = 0
for attr, value in target_attributes.items():
el_attr = el.get_attribute(attr) or ""
score += similarity(el_attr, value)
if score > best_score:
best_score = score
best_element = el
return best_element if best_score > 0.6 else None
# Usage
element = find_best_candidate(driver, {
"id": "submit-btn",
"class": "btn-primary",
"type": "submit"
})
실제 운영 환경에서는 유사도 점수 계산기를 임베딩 모델(OpenAI, Sentence Transformers)로 교체하여 요소 컨텍스트의 의미적 유사성을 비교하도록 합니다 — 단순히 속성 문자열만 비교하는 것이 아니라.
루프 닫기: 자동 업데이트 로케이터
마지막 단계는 승리한 로케이터를 테스트 구성 파일에 다시 기록하여 이후 실행에서 직접 사용할 수 있게 하는 것입니다:
import json
def update_locator_store(key, strategy, locator, path="locators.json"):
with open(path, "r+") as f:
store = json.load(f)
store[key] = {"strategy": strategy, "locator": locator}
f.seek(0)
json.dump(store, f, indent=2)
이 과정을 CI 파이프라인과 결합하여 로케이터가 복구될 때 PR이나 댓글을 자동으로 생성하도록 하면, 팀이 수동 개입 없이도 가시성을 확보할 수 있습니다.
언제 Not to Use This
Self‑healing은 복잡성을 추가합니다. 앱에 안정적인 디자인 시스템과 체계적인 data-testid 사용이 있다면, 아마도 필요하지 않을 것입니다. 이 패턴이 가장 가치 있는 경우는 다음과 같습니다:
- 불안정한 DOM 구조를 가진 레거시 앱
- 개발자와 QA가 분리된 팀
- 테스트 소유권 없이 UI를 자주 재디자인하는 경우
더 나아가기 위한 팁
- Healenium — 기존 Selenium 설정에 최소한의 코드 변경으로 자체 치유 기능을 추가하는 오픈소스 프록시
- Sentence Transformers — 코사인 유사도는
SequenceMatcher보다 더 나은 의미 매칭을 제공합니다 - 모든 치유 이벤트를 대시보드에 기록하세요 — 설계 불안정 패턴을 빠르게 파악할 수 있습니다