JavaFX 자동화 테스트

JavaFX 자동화 테스트

TestFX로 LogoRRR 테스트하기

LogoRRR은 JavaFX 사용자 인터페이스에 대한 통합 테스트를 실행하기 위해 TestFX를 사용합니다. 이러한 테스트는 새로운 기능 추가, 리팩토링 및 종속성 업데이트 과정에서도 핵심 워크플로우가 유지된다는 확신을 주며, 단위 테스트만으로는 발견할 수 없는 회귀 오류를 잡아냅니다.

왜 지금인가

20개 이상의 릴리스를 거치면서 LogoRRR은 수동 테스트만으로는 더 이상 충분하지 않을 만큼 복잡해졌습니다. 코드베이스에는 안전망이 필요했습니다. TestFX를 사용하면 JUnit 테스트 메서드에서 버튼 클릭, 파일 열기, UI 상태 검사 등 실제 애플리케이션 창을 직접 구동할 수 있습니다.

엔드 투 엔드 테스트에 언제 투자할 것인가는 항상 트레이드오프의 문제입니다. 프로젝트 초기에는 UI가 너무 빨리 변해서 테스트가 따라가기 어렵습니다. 하지만 핵심 흐름이 안정화되면 테스트는 부담이 아니라 가속 장치가 됩니다. 그 전환점이 24.3.0 버전과 함께 찾아왔습니다.

구현

Scala의 간결한 구문은 소규모 테스트 DSL을 구축하는 데 자연스럽게 어울립니다. 파일 열기, 닫기 버튼 클릭, 탭 패인이 비어 있는지 확인하는 등 각각의 원자적 동작은 읽기 쉬운 빌딩 블록이 됩니다.

@Test def openAndCloseTab(): Unit = {
    checkForEmptyTabPane()
    openFile(path)
    checkForNonEmptyTabPane()
    clickOn(lookup(UiNodes.LogFileHeaderTabs).query[StackPane](), MouseButton.SECONDARY)
    waitAndClickVisibleItem(CloseTabMenuItem.uiNode(fileId))
    checkForEmptyTabPane()
}

프론트엔드 테스트를 작성하면서 프로덕션 코드도 개선되었습니다. 파일 I/O 및 외부 프로세스 호출을 추상화하기 위해 새로운 서비스(Service) 레이어가 추가되었으며, 이는 테스트 이점과는 별개로 아키텍처를 개선하는 효과를 가져왔습니다.

테스트를 통해 발견한 것들

  • 애플리케이션 종료 동작 — 제대로 정리되지 않았던 리소스들이 테스트를 통해 명확하게 드러났습니다.
  • 테스트 격리 — 각 테스트는 자체 상태를 설정하고 해제해야 하므로, 공유 UI 상태에 대한 몇 가지 미묘한 가정들이 드러났습니다.
  • 성능 기준선 — 테스트 실행 시간을 주시함으로써 느린 테스트가 점진적으로 쌓이는 것을 방지합니다.
LogoRRR 테스트 스위트를 실행하는 TestFX — 사용자가 수행하는 것과 동일한 상호작용이 자동으로 실행됩니다

헤더 사진: Pexels의 Sora Shimazaki