본문 바로가기
Development/Android

[Android] Android Fragment 테스트 핵심 방법

by 은스타 2019. 9. 6.
반응형
Android Fragment 테스트 핵심 방법

Android Fragment 테스트 핵심 방법

Android Fragment는 앱 내에서 재사용 가능한 컨테이너 역할을 하며, 다양한 Activity와 레이아웃 구성에서 동일한 사용자 인터페이스를 표시합니다. Fragment의 일관적인 동작과 효율적인 리소스 사용을 검증하는 것은 앱 품질 향상의 필수 요소입니다. 이번 글에서는 Fragment 테스트를 위한 FragmentScenario 라이브러리의 활용법과 실무 테스트 패턴을 소개합니다.
목차
1. Fragment 테스트의 중요성과 핵심 원칙
2. FragmentScenario 환경 설정 방법
3. Fragment 생성 및 실행 패턴
4. Fragment 생명주기 테스트 기법
5. Fragment 상호작용 테스트 구현

#1. Fragment 테스트의 중요성과 핵심 원칙
1) Fragment 테스트가 필요한 이유
Fragment는 다양한 화면 크기와 방향에서 재사용되는 UI 컴포넌트입니다. 일관된 사용자 경험을 제공하기 위해서는 체계적인 테스트가 필수적입니다.
(1) UI 일관성 검증
Fragment의 외형은 대형 스크린 화면이나 가로 모드를 포함한 모든 레이아웃 구성에서 일관적이어야 합니다. 다양한 디바이스 환경에서 동일한 사용자 경험을 제공하는지 확인해야 합니다.
(2) 리소스 효율성 확인
Fragment가 사용자에게 보일 경우에만 뷰 계층 구조를 생성하도록 구현되었는지 검증합니다. 불필요한 리소스 소비를 방지하여 앱 성능을 최적화할 수 있습니다.
. . . . .
2) Fragment 테스트의 핵심 검증 항목
검증 항목 설명 중요도
생명주기 전환 Fragment의 상태 변경이 올바르게 처리되는지 확인 높음
뷰 렌더링 UI 요소가 예상대로 표시되고 동작하는지 검증 높음
데이터 유지 화면 회전 등 재생성 시 데이터 보존 여부 확인 중간
메모리 관리 리소스 해제가 적절하게 이루어지는지 검증 중간

#2. FragmentScenario 환경 설정 방법
1) FragmentScenario 라이브러리 소개
AndroidX는 Fragment를 생성하고 상태를 변경하기 위한 FragmentScenario 라이브러리를 제공합니다. 이 라이브러리를 활용하면 테스트 환경에서 Fragment의 생명주기를 쉽게 제어할 수 있습니다.
(1) 스레드 처리 주의사항
Test 계측 스레드에서 각 API 메서드를 실행해야 합니다. FragmentScenario 객체가 포함된 테스트를 성공적으로 실행하려면 스레드 관리가 필수적입니다.
. . . . .
2) 의존성 추가 및 설정
(1) Gradle 설정
FragmentScenario를 사용하려면 app/build.gradle 파일에 Fragment test artifact를 추가해야 합니다.
dependencies {
// Fragment 테스트 라이브러리
debugImplementation 'androidx.fragment:fragment-testing:1.6.2'

// AndroidX Test 라이브러리
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test:rules:1.5.0'

// Espresso UI 테스트 라이브러리
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
(2) Test artifact 위치 구성
Fragment test artifact는 앱의 테스트 APK에 포함되어야 합니다. debugImplementation을 사용하여 디버그 빌드에만 포함되도록 설정합니다.

#3. Fragment 생성 및 실행 패턴
1) Fragment 타입별 실행 메서드
FragmentScenario는 Fragment의 특성에 따라 두 가지 실행 메서드를 제공합니다.
(1) 그래픽 Fragment 실행
사용자 인터페이스를 포함하는 그래픽 Fragment는 launchFragmentInContainer() 메서드를 사용합니다. FragmentScenario는 Fragment를 Activity의 루트 뷰 컨트롤러에 연결하며, 컨테이너 Activity는 비어 있는 상태입니다.
@RunWith(AndroidJUnit4::class)
class GraphicFragmentTest {

@Test
fun testUserInterfaceFragment() {
// Fragment 인자 설정
val fragmentArgs = Bundle().apply {
putInt("selectedListItem", 0)
putString("userId", "test_user")
}

// Fragment Factory 생성 (선택사항)
val factory = MyFragmentFactory()

// Fragment 실행
val scenario = launchFragmentInContainer<MyFragment>(
fragmentArgs,
factory
)

// UI 검증
onView(withId(R.id.text))
.check(matches(withText("Hello World!")))
}
}
(2) 비그래픽 Fragment 실행
여러 Activity에 포함된 정보를 실행하거나 저장하는 비그래픽 Fragment는 launchFragment() 메서드를 사용합니다. 루트 뷰가 없는 완전히 빈 Activity에 연결됩니다.
@RunWith(AndroidJUnit4::class)
class NonGraphicFragmentTest {

@Test
fun testDataFragment() {
// Fragment 인자 설정
val fragmentArgs = Bundle().apply {
putInt("numElements", 10)
}

val factory = MyFragmentFactory()

// 비그래픽 Fragment 실행
val scenario = launchFragment<MyFragment>(
fragmentArgs,
factory
)

// Fragment 동작 검증
scenario.onFragment { fragment ->
assertThat(fragment.dataList.size).isEqualTo(10)
}
}
}
. . . . .
2) Fragment 초기 상태
Fragment를 실행하면 FragmentScenario는 테스트 중인 Fragment를 RESUMED 상태로 자동 전환합니다. 이는 Fragment가 실행 중이며 사용자와 상호작용 가능한 상태를 의미합니다.
그래픽 Fragment의 경우 사용자에게 보이는 상태이므로 Espresso UI 테스트를 활용하여 UI 요소를 검증할 수 있습니다.

#4. Fragment 생명주기 테스트 기법
1) Fragment 재생성 테스트
디바이스 리소스가 부족할 때 시스템은 Fragment가 포함된 Activity를 소멸시킬 수 있습니다. 사용자가 앱에 돌아오면 Fragment를 재생성해야 하는데, 이 상황을 시뮬레이션하여 테스트할 수 있습니다.
(1) recreate() 메서드 활용
@RunWith(AndroidJUnit4::class)
class FragmentRecreationTest {

@Test
fun testFragmentRecreation() {
val scenario = launchFragmentInContainer<MyFragment>()

// Fragment 재생성 시뮬레이션
scenario.recreate()

// 데이터 유지 검증
onView(withId(R.id.text))
.check(matches(withText("Preserved Data")))
}
}
FragmentScenario가 Fragment를 재생성하면, Fragment는 재생성 이전의 생명주기 상태로 복원됩니다.
. . . . .
2) 생명주기 상태 전환 테스트
Fragment가 다양한 생명주기 상태를 거치며 올바르게 동작하는지 검증할 수 있습니다. moveToState() 메서드를 사용하여 특정 상태로 전환합니다.
(1) 지원되는 생명주기 상태
moveToState() 메서드는 다음 상태를 인수로 지원합니다:
CREATED: Fragment가 생성되었지만 뷰는 아직 생성되지 않은 상태
STARTED: Fragment의 뷰가 생성되었지만 아직 화면에 보이지 않는 상태
RESUMED: Fragment가 화면에 표시되고 사용자와 상호작용 가능한 상태
DESTROYED: Fragment가 완전히 소멸된 상태
(2) 상태 전환 테스트 예시
@RunWith(AndroidJUnit4::class)
class FragmentLifecycleTest {

@Test
fun testFragmentStateTransition() {
val scenario = launchFragmentInContainer<MyFragment>()

// CREATED 상태로 전환
scenario.moveToState(Lifecycle.State.CREATED)

// 뷰가 소멸되었는지 확인
scenario.onFragment { fragment ->
assertThat(fragment.view).isNull()
}

// RESUMED 상태로 복원
scenario.moveToState(Lifecycle.State.RESUMED)
}
}
(3) 상태 전환 주의사항
Fragment를 DESTROYED 상태로 전환하면 다른 상태로 변경할 수 없습니다. 또한 Fragment를 다른 Activity에 연결할 수도 없게 됩니다.
테스트 중인 Fragment를 현재와 동일한 상태로 전환하려고 하면, FragmentScenario는 이를 예외가 아닌 작업 불능으로 처리합니다. 특히 DESTROYED 상태로 여러 번 연속 전환할 수 있습니다.

#5. Fragment 상호작용 테스트 구현
1) Espresso를 활용한 UI 상호작용 테스트
테스트 중인 Fragment에서 사용자 동작을 시뮬레이션하려면 Espresso 뷰 매처를 사용합니다.
(1) 뷰 클릭 이벤트 테스트
@RunWith(AndroidJUnit4::class)
class FragmentInteractionTest {

@Test
fun testButtonClick() {
val scenario = launchFragmentInContainer<MyFragment>()

// 새로고침 버튼 클릭
onView(withId(R.id.refresh))
.perform(click())

// 결과 검증
onView(withId(R.id.status))
.check(matches(withText("Refreshed")))
}
}
. . . . .
2) Fragment 메서드 직접 호출
Fragment의 메서드를 직접 호출해야 하는 경우 FragmentAction을 구현하여 안전하게 호출할 수 있습니다.
(1) onFragment() 메서드 활용
@RunWith(AndroidJUnit4::class)
class FragmentMethodTest {

@Test
fun testOptionsMenuSelection() {
val scenario = launchFragmentInContainer<MyFragment>()

// Fragment 메서드 호출
scenario.onFragment { fragment ->
fragment.onOptionsItemSelected(clickedItem)
}

// 상태 변경 확인
scenario.onFragment { fragment ->
assertThat(fragment.currentState).isEqualTo(UPDATED)
}
}
}
(2) Fragment 참조 관리 주의사항
테스트 클래스에서 onFragment()로 전달받은 객체에 대한 참조를 보관하지 마세요. 이 참조는 시스템 리소스를 사용하며, 프레임워크가 콜백 메서드로 전달된 Fragment를 재생성할 수 있어 참조가 최신이 아닐 수 있습니다.
. . . . .
3) Fragment 테스트 베스트 프랙티스
구분 권장사항 이유
참조 관리 Fragment 인스턴스를 로컬 변수로 저장하지 않기 재생성 시 참조가 무효화될 수 있음
스레드 처리 Test 계측 스레드에서 API 호출 스레드 안전성 보장
상태 전환 DESTROYED 상태 전환 후 재사용 금지 생명주기 규칙 준수
UI 검증 Espresso 매처 활용 안정적인 UI 테스트 보장

마무리
Android Fragment 테스트는 FragmentScenario 라이브러리를 활용하여 체계적으로 수행할 수 있습니다. 그래픽과 비그래픽 Fragment의 구분, 생명주기 상태 전환, UI 상호작용 검증 등 다양한 테스트 패턴을 이해하고 적용하면 안정적인 앱을 구축할 수 있습니다.
Fragment 테스트의 핵심은 실제 사용자 시나리오를 시뮬레이션하는 것입니다. 디바이스 리소스 부족 상황, 화면 회전, 백그라운드 전환 등 다양한 상황에서 Fragment가 올바르게 동작하는지 검증하세요. Espresso와 FragmentScenario를 조합하면 강력하고 유지보수 가능한 테스트 코드를 작성할 수 있습니다.
긴 글 읽어주셔서 감사합니다.

끝.
반응형