테스트 코드에서만 접근 가능한 의존성 만들기
지난 몇 주간 쿠링 안드로이드 앱을 모듈화하고 있다. 여러 이슈가 있었지만 선배님과 함께 잘 풀어나가고 있다. 그 중에서도 오늘은 Gradle의 기능과 관련된 사례 하나를 소개하려 한다.
앱에서 사용하는 도메인 클래스를 ``:data:domain`` 모듈로 옮겼다. 동시에 테스트 코드에 있던 도메인 클래스의 mock 코드를 클래스의 정의로 옮겼다.
data class Department(
val name: String,
val shortName: String,
val koreanName: String,
val isSubscribed: Boolean,
val isSelected: Boolean,
val isNotificationEnabled: Boolean,
) {
companion object {
fun mock() = Department(
name = "computer_science",
shortName = "cse",
koreanName = "컴퓨터공학부",
isSubscribed = false,
isSelected = false,
isNotificationEnabled = false,
)
}
}
그런데 선배님께서 이런 코멘트를 남겨 주셨다.
선배님: 테스트를 위한 코드는 테스트 패키지에서 관리하는 게 좋지 않을까요?
나: Compose Preview용 샘플 데이터로도 쓸 수 있어서, 테스트용 mock이 아니라 fake 데이터 같은 느낌으로 이해하면 되지 않을까요?
선배님: (전략) 프로덕션 코드에 테스트를 위한 함수가 끼어드는 건 주객전도 같아 보입니다. 조금 귀찮더라도 테스트용 데이터는 테스트 쪽에서 만드는 게 좋지 않을까 하는 의견입니다.
나: 그러면 1) 테스트 코드에서만 접근 가능할 것, 2) 여러 모듈에서 접근할 수 있어야 할 것 중 1)번을 중시하는 게 맞다는 말씀이신가요?
선배님: 1)번의 우선순위가 더 높다고 생각해요. 둘 다 충족시키면 제일 좋겠지만... 어떻게 될 것 같은데...
그래서 찾아 본 결과, 이미 Gradle에서 테스트 패키지의 코드를 공유할 수 있는 기능을 지원하고 있었다.
Test Fixtures
Test Fixtures는 테스트 코드 간 의존성을 공유하는 데 사용될 수 있다. 위의 예시로 설명하자면 ``Notice.mock()`` 함수를 테스트 코드끼리만 공유할 수 있다는 뜻이다.
AGP 7.2.0 이상과 Gradle 7.3.3 이상 버전이 요구된다. 요구사항을 먼저 확인하자.
이제 실제로 구현해 보자. ``:data:domain`` 모듈에 ``gradle-text-fixtures`` 플러그인을 추가한 후, ``android`` 블럭에 test fixtures 기능을 추가했다.
plugins {
// ...
id 'java-test-fixtures'
}
android {
// ...
testFixtures {
enable true
}
}
이제 ``src\testFixtures\java`` 경로에 공유할 코드를 작성하면 된다.
object KuringFixtures {
fun noticeFixture() = Notice(
postedDate = "20220203",
subject = "2022학년도 1학기 재입학 합격자 유의사항 안내",
category = "bachelor",
url = "https://www.konkuk.ac.kr/do/MessageBoard/ArticleRead.do?id=5b4a11b",
articleId = "5b4a11b",
isNew = true,
isRead = false,
isSubscribing = false,
isSaved = false,
isReadOnStorage = false,
tag = emptyList()
)
}
의존성 추가
작성한 test fixtures에 의존할 모듈에 다음과 같이 의존성을 추가하자.
testImplementation testFixtures(project(":data:domain"))
이제 테스트 코드에서 test fixtures에 접근할 수 있다!
@Test
fun `insert Notice As Old Test`() {
val mockData = KuringFixtures.notice()
// ...
}
자 이제 테스트를 실행해 보면?
에러
Unresolved reference: KuringFixtures
검색해 보니, Android Gradle Plugin에서 Kotlin 코드로 작성된 test fixtures를 지원하지 않는다고 한다. 참고로 Android가 아닌 일반 Kotlin 프로젝트에서는 Kotlin test fixtures를 사용할 수 있다.
구글 맞을래요?
아래 링크에서 해당 이슈의 진행 상황을 살펴볼 수 있다. 원래 AGP 8.1에서 지원될 예정이었지만, 8.3으로 연기되었다. 일단 8.3.0-alpha06까지는 해결되지 않은 상황.
해결 방법
Java로 작성한 Test fixtures는 정상적으로 사용할 수 있다. 따라서 일단 Java로 작성한 후, 나중에 Kotlin으로 변환하면 된다.
Kotlin test fixtures가 지원되면 이 글을 업데이트하겠다.
정리
Test fixtures를 사용하면 테스트 코드에서만 사용할 유틸, 데이터 등을 프로덕션에 노출하지 않고도 여러 모듈 간에 공유할 수 있다. 다만 Android Kotlin 프로젝트에서 지원되지 않는 점이 아쉽다. AGP 8.3.0이 빨리 출시됐으면 좋겠다.