WebDriver 완벽 마스터
WebDriver의 핵심 개념과 실전 활용법
학습 항목
이미지 로딩 중...
Selenium 베스트 프랙티스 완벽 가이드
안정적이고 유지보수하기 쉬운 Selenium 테스트 코드를 작성하는 방법을 다룹니다. 실무에서 바로 적용 가능한 고급 패턴과 최적화 기법을 소개합니다.
들어가며
이 글에서는 Selenium 베스트 프랙티스 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- Explicit_Wait_사용하기
- Page_Object_Pattern
- 상대적_Locator_활용
- 예외_처리와_재시도_로직
- 스크린샷_자동_캡처
- Custom_Expected_Conditions
- 암묵적_대기_제거
- JavaScript_Executor_활용
- 헤드리스_모드_설정
- Select_드롭다운_처리
- 윈도우_핸들_관리
- 동적_요소_대기_전략
1. Explicit_Wait_사용하기
개요
암묵적 대기 대신 명시적 대기를 사용하여 요소가 특정 조건을 만족할 때까지 기다립니다. 테스트의 안정성을 크게 향상시킵니다.
코드 예제
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 10)
element = wait.until(
EC.presence_of_element_located((By.ID, "submit-btn"))
)
element.click()
설명
최대 10초 동안 요소가 DOM에 존재할 때까지 기다린 후 클릭합니다. 타이밍 이슈로 인한 테스트 실패를 방지합니다.
2. Page_Object_Pattern
개요
페이지의 요소와 동작을 클래스로 캡슐화하여 코드 재사용성과 유지보수성을 높입니다. 테스트 코드와 페이지 로직을 분리합니다.
코드 예제
class LoginPage:
def __init__(self, driver):
self.driver = driver
self.username = (By.ID, "username")
self.password = (By.ID, "password")
def login(self, user, pwd):
self.driver.find_element(*self.username).send_keys(user)
self.driver.find_element(*self.password).send_keys(pwd)
설명
로그인 페이지의 요소와 동작을 하나의 클래스로 관리하여 여러 테스트에서 재사용할 수 있습니다.
3. 상대적_Locator_활용
개요
다른 요소를 기준으로 상대적 위치의 요소를 찾습니다. 복잡한 DOM 구조에서 정확한 요소 선택이 가능합니다.
코드 예제
from selenium.webdriver.support.relative_locator import locate_with
password_field = driver.find_element(By.ID, "password")
submit_button = driver.find_element(
locate_with(By.TAG_NAME, "button")
.below(password_field)
)
submit_button.click()
설명
비밀번호 필드 아래에 있는 버튼을 찾아 클릭합니다. ID나 클래스가 없어도 위치 기반으로 요소를 찾을 수 있습니다.
4. 예외_처리와_재시도_로직
개요
네트워크 지연이나 일시적 오류에 대비한 재시도 메커니즘을 구현합니다. 테스트의 신뢰성을 높입니다.
코드 예제
from selenium.common.exceptions import StaleElementReferenceException
def click_with_retry(driver, locator, retries=3):
for i in range(retries):
try:
element = driver.find_element(*locator)
element.click()
return
except StaleElementReferenceException:
if i == retries - 1:
raise
설명
DOM이 업데이트되어 요소 참조가 끊어졌을 때 최대 3번까지 재시도합니다. 동적 페이지에서 발생하는 오류를 해결합니다.
5. 스크린샷_자동_캡처
개요
테스트 실패 시 자동으로 스크린샷을 저장하여 디버깅을 용이하게 합니다. 실패 원인 파악이 빨라집니다.
코드 예제
import pytest
from datetime import datetime
@pytest.fixture
def driver_with_screenshot(driver, request):
yield driver
if request.node.rep_call.failed:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
driver.save_screenshot(f"failure_{timestamp}.png")
설명
테스트가 실패하면 자동으로 타임스탬프가 포함된 이름의 스크린샷을 저장합니다. CI/CD 환경에서 특히 유용합니다.
6. Custom_Expected_Conditions
개요
복잡한 대기 조건을 커스텀 함수로 만들어 재사용합니다. 표준 조건으로 처리할 수 없는 상황에 대응합니다.
코드 예제
class element_has_css_class:
def __init__(self, locator, css_class):
self.locator = locator
self.css_class = css_class
def __call__(self, driver):
element = driver.find_element(*self.locator)
return self.css_class in element.get_attribute("class")
wait.until(element_has_css_class((By.ID, "status"), "active"))
설명
특정 요소가 'active' 클래스를 가질 때까지 기다립니다. 복잡한 UI 상태 변화를 정확히 감지할 수 있습니다.
7. 암묵적_대기_제거
개요
implicitly_wait 대신 명시적 대기만 사용합니다. 예측 가능한 테스트 타이밍을 보장합니다.
코드 예제
# 나쁜 예
driver.implicitly_wait(10)
# 좋은 예
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.ID, "btn")))
설명
암묵적 대기는 모든 요소 검색에 영향을 주어 예상치 못한 지연을 발생시킵니다. 명시적 대기로 정확한 제어가 가능합니다.
8. JavaScript_Executor_활용
개요
Selenium으로 처리하기 어려운 동작을 JavaScript로 직접 실행합니다. 복잡한 인터랙션을 간단히 처리합니다.
코드 예제
# 숨겨진 요소 클릭
element = driver.find_element(By.ID, "hidden-btn")
driver.execute_script("arguments[0].click();", element)
# 스크롤
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
설명
화면에 보이지 않거나 다른 요소에 가려진 버튼을 JavaScript로 직접 클릭하고, 페이지 하단으로 스크롤합니다.
9. 헤드리스_모드_설정
개요
GUI 없이 백그라운드에서 브라우저를 실행합니다. CI/CD 환경에서 빠른 테스트 실행이 가능합니다.
코드 예제
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)
설명
헤드리스 모드로 Chrome을 실행하고 샌드박스를 비활성화하여 Docker 환경에서도 안정적으로 작동합니다.
10. Select_드롭다운_처리
개요
드롭다운 메뉴를 쉽게 조작하는 Select 클래스를 사용합니다. 값, 인덱스, 텍스트로 선택 가능합니다.
코드 예제
from selenium.webdriver.support.select import Select
dropdown = Select(driver.find_element(By.ID, "country"))
dropdown.select_by_visible_text("Korea")
dropdown.select_by_value("KR")
dropdown.select_by_index(2)
설명
드롭다운에서 보이는 텍스트, value 속성, 인덱스 등 다양한 방법으로 옵션을 선택할 수 있습니다.
11. 윈도우_핸들_관리
개요
팝업이나 새 탭을 올바르게 전환하고 관리합니다. 멀티 윈도우 환경에서 안정적인 테스트가 가능합니다.
코드 예제
main_window = driver.current_window_handle
driver.find_element(By.LINK_TEXT, "Open New Tab").click()
for handle in driver.window_handles:
if handle != main_window:
driver.switch_to.window(handle)
break
driver.close()
driver.switch_to.window(main_window)
설명
새 탭이 열리면 해당 탭으로 전환하여 작업을 수행하고, 작업 후 닫은 뒤 원래 탭으로 돌아갑니다.
12. 동적_요소_대기_전략
개요
AJAX 요청이나 애니메이션이 완료될 때까지 기다립니다. SPA 환경에서 필수적인 패턴입니다.
코드 예제
from selenium.webdriver.support.ui import WebDriverWait
def wait_for_ajax(driver):
wait = WebDriverWait(driver, 10)
wait.until(lambda d: d.execute_script(
"return jQuery.active == 0"
))
wait_for_ajax(driver)
element = driver.find_element(By.CLASS_NAME, "result")
설명
jQuery를 사용하는 페이지에서 모든 AJAX 요청이 완료될 때까지 기다린 후 결과 요소를 찾습니다.
마치며
이번 글에서는 Selenium 베스트 프랙티스 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Selenium #WebDriver #PageObject #ExplicitWait #TestAutomation