Flaky Test와의 전쟁: Playwright로 테스트 신뢰도를 높이다!
Robot Framework의 한계로 인해 발생한 Flaky Test 문제를 해결하기 위해 Playwright로 마이그레이션(Migration)을 진행
자동 대기(Auto-wait), DOM 기반 Selector 전략 등 Playwright의 장점을 활용하여 테스트의 안정성을 확보
데이터의 불안정성을 극복하기 위해 팝업 처리, 시간대 예외 처리 등 테스트 로직(Test Logic) 개선을 시도
데이터 개수에 따라 테스트 수행 여부를 결정하는 Dynamic Skip 로직을 도입하여 테스트 신뢰도 향상
테스트 환경 변화에 유연하게 대응하기 위해 지속적인 테스트 코드(Test Code) 유지보수의 중요성을 강조
Headless 모드(Headless Mode) 환경에서의 테스트 불안정성
본문에서는 기존 Robot Framework + Selenium 환경에서 Headless 모드(Headless Mode) 실행 시 요소 탐색 실패율이 높았다고 지적한다. 이는 Headless 환경의 렌더링(Rendering) 문제 또는 요소 탐색 방식의 한계 때문일 수 있다.
Playwright: 자동 대기(Auto-wait) 기능을 통해 요소의 가시성(Visibility)을 자동으로 감지하여 테스트 안정성 확보
Selenium: 명시적인 대기(Explicit Wait)를 사용해야 하므로, 테스트 코드(Test Code) 복잡도 증가 및 유지보수 어려움 발생
Headless 모드: GUI 환경과 다른 렌더링 방식으로 인해, 요소 탐색 실패 가능성이 높음. 따라서, Headless 환경에 맞는 테스트 코드 설계가 중요하며, Playwright의 자동 대기 기능은 이러한 문제를 완화하는 데 기여한다.
DOM(Document Object Model) 기반 Selector 전략
테스트 자동화에서 DOM(Document Object Model) 구조는 UI 요소(UI Element)를 식별하는 핵심 수단이지만, 웹 페이지의 동적인 특성으로 인해 DOM 구조는 자주 변경된다. 본문에서는 단순히 DOM 순서에 의존하는 대신, UX(User Experience)에 기반한 Selector 전략을 통해 테스트의 견고함을 높였다.
정규식(Regular Expression) 활용: 텍스트 기반 요소(Text-based Element) 검증을 통해, UI 변경에 유연하게 대응
Visibility 필터(Visibility Filter) 적용: 화면에 보이는 요소만 선택하여, 숨겨진 요소로 인한 오동작 방지
DOM 구조의 변화: 웹 프레임워크(Web Framework) 업데이트 또는 UI 컴포넌트(UI Component) 변경 시, 기존 Selector가 무효화될 수 있음. 따라서, 유지보수성을 고려한 Selector 전략이 필요하다.
데이터의 불안정성에 대응하는 테스트 로직
테스트 환경의 데이터는 시시각각 변동될 수 있으며, 이는 Flaky Test의 주요 원인 중 하나이다. 본문에서는 팝업 처리, 시간대 예외 처리, 데이터 개수 기반 Dynamic Skip 등 다양한 로직을 통해 데이터의 불안정성에 대응했다.
팝업 Interception: 전역 핸들러(Global Handler) 등록을 통해, 팝업 발생 시 자동 닫기 처리
시간대 예외 처리: Pytest Marker와 Hook을 활용하여, 특정 시간대(00:00~00:10)의 테스트 스킵
Dynamic Skip: 데이터 개수(Data Count) 기반 조건부 테스트 실행을 통해, 불필요한 테스트 수행 방지
데이터의 변동성을 고려한 테스트 로직 설계는 테스트의 신뢰도(Test Reliability)를 향상시키고, 불필요한 실패를 줄이는 데 기여한다.
Pytest Hook을 활용한 테스트 제어
Pytest는 테스트 실행 전후에 특정 동작을 수행할 수 있는 Hook 기능을 제공한다. 본문에서는 자정 시간대의 테스트 실패를 해결하기 위해 Pytest Hook을 활용하여, 특정 시간대에 테스트를 스킵하는 전략을 사용했다.
@pytest.mark.skip_at_midnight: Custom Marker를 생성하여, 자정에 실행하면 안 되는 테스트에 적용
pytest_runtest_setup: Hook 함수(Hook Function)를 구현하여, 현재 시간이 자정 직후 10분 이내일 경우 테스트 스킵
테스트 스킵(Test Skip): 테스트 실행 자체를 건너뜀으로써, 특정 시간대의 데이터 갱신 지연으로 인한 오류 방지
Pytest Hook을 활용하면, 테스트 실행 흐름을 유연하게 제어하고, 테스트 환경의 특수성을 반영하여 테스트의 신뢰도를 높일 수 있다.
테스트 자동화의 지속적인 유지보수
테스트 자동화는 한 번 구축으로 끝나는 것이 아니라, 지속적인 유지보수를 통해 테스트의 신뢰도를 유지해야 한다. 본문에서는 UI 변경, 로직 변경 등 환경 변화에 대응하기 위한 지속적인 코드 유지보수의 중요성을 강조한다.
UI 변경: Selector 전략(Selector Strategy) 개선 및 테스트 코드(Test Code) 리팩토링(Refactoring)을 통해, UI 변경에 유연하게 대응
로직 변경: 테스트 케이스(Test Case) 업데이트 및 새로운 테스트 추가를 통해, 로직 변경에 대응
간헐적 Fail 케이스: 지속적인 모니터링(Monitoring) 및 분석을 통해, 간헐적 오류(Intermittent Error)를 찾아내고 해결
테스트 자동화 환경은 끊임없이 변화하므로, 지속적인 유지보수(Continuous Maintenance)를 통해 테스트의 신뢰도를 확보하고, 안정적인 자동화 환경을 구축해야 한다.