Skip to content

Test convention

정제훈 edited this page Mar 4, 2026 · 1 revision

테스트 위치

모듈 기준으로 테스트를 분리해서 작성한다.

  • 단위 테스트 -> module/src/test/java/...
  • 계측 테스트 -> module/src/androidTest/java/...
  • 운영 코드 패키지 구조를 맞춘다 -> app/src/test/java/com/eatssu/android/presentation/...

테스트 클래스 파일명

대상 이름 + BehaviorSpec 접미사를 사용한다.

  • ViewModel -> LoginViewModelBehaviorSpec.kt, MapViewModelBehaviorSpec.kt
  • UseCase -> GetMenuListUseCaseBehaviorSpec.kt
  • Repository -> MenuRepositoryImplBehaviorSpec.kt

테스트 스펙 구조

Kotest BehaviorSpec + given/when/then 순서, 구조로 작성한다.

  • 설명 문자열은 한국어로 작성한다 -> given("카카오 로그인")
  • Kotlin 키워드 충돌 구문은 백틱을 사용한다 -> `when`("토큰 발급이 성공하면")
  • 기대 결과 중심으로 작성한다 -> then("토큰과 이메일을 저장하고 성공 상태가 된다")

app 모듈 공통 베이스

app 단위 테스트는 AppBehaviorSpec 상속을 기본으로 한다.

  • 공통 리스너 등록 -> listener(MainDispatcherListener())
  • 메인 디스패처 제어 -> Dispatchers.setMain(...), Dispatchers.resetMain()
  • 테스트 후 목 정리 -> clearAllMocks(...), unmockkAll()

코루틴/Flow 테스트

비동기 테스트는 공통 패턴으로 작성한다.

  • 코루틴 테스트 -> runTest { ... }
  • 상태 수렴 검증 -> eventually(2.seconds) { ... }
  • UI 이벤트 검증 -> uiEvent.test { ... }
  • 남은 이벤트 정리 -> cancelAndIgnoreRemainingEvents()

MockK 사용 규칙

MockK API를 목적에 맞게 구분해서 사용한다.

  • suspend stubbing -> coEvery { ... } returns ...
  • 일반 stubbing -> every { ... } just Runs
  • suspend 검증 -> coVerify { ... }
  • 일반 검증 -> verify { ... }
  • 호출 횟수는 명시한다 -> exactly = 0, exactly = 1, atLeast = 1

테스트 데이터/헬퍼

반복 데이터와 검증 코드는 공통 파일로 분리한다.

  • 샘플 데이터 팩토리 -> sampleUserInfo(), sampleToken(), sampleReview()
  • 이벤트 검증 헬퍼 -> awaitToastEvent(), expectToast(), expectNavigateBack()
  • 상태 데이터 헬퍼 -> successDataAs<T>()

androidTest 규칙

현재 androidTest는 JUnit4 기반 기본 패턴을 사용한다.

  • 러너 어노테이션 -> @RunWith(AndroidJUnit4::class)
  • 테스트 함수 -> @Test
  • 컨텍스트 접근 -> InstrumentationRegistry.getInstrumentation().targetContext
  • 러너 설정 -> testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

테스트 라이브러리

단위 테스트는 아래 조합을 기본으로 사용한다.

  • 스펙/매처 -> kotest
  • 목킹 -> mockk
  • 코루틴 테스트 -> kotlinx-coroutines-test
  • Flow 검증 -> turbine

Clone this wiki locally