안드로이드 프레임워크가 연관되는 모듈은 jvm 위에서는 실행할 수가 없다.
따라서 테스트를 에뮬레이터나 실기기 위에서 수행해야 되는데 이것을 인스트루먼티드 유닛 테스트라고 합니다
여기서는 예제로 메인 액티비티를 생성한 다음에 그 라이프사이클 상태를 확인하는 인스트루먼티드 테스트를 해보겠습니다
우선은 테스트에 필요한 Dependency를 추가해줍니다
androidTestImplementation "androidx.test:core:1.5.0"
androidTestImplementation "androidx.test.ext:trush:1.5.0"
androidTestImplementation "androidx.test:rules:1.5.0"
다음은 MainActivity 클래스로부터 테스트를 작성해 보겠습니다. 이름은 MainActivityTest로 하고 테스트 라이브러리는 JUnit4로 하겠습니다. 그리고 안드로이드 SDK를 사용해야 되기 때문에 파일은 android-test 디렉토리에 저장하도록 하겠습니다
테스트를 실행할 런너를 runwith로 지정을 해주는데 여기서는 android-junit4로 지정하겠습니다.
그러면은 코드를 써보도록 하겠습니다
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.*
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SmallTest
class MainActivityTest {
// private lateinit var activityScenario: ActivityScenario<MainActivity>
// @Before
// fun setUp() {
// activityScenario = ActivityScenario.launch(MainActivity::class.java)
// }
//
// @After
// fun tearDown() {
// activityScenario.close()
// }
// 위 처럼 생성하고 닫는 작업을 해주는 것을 Rule을 사용하면 편하게 사용이 가능하다.
@get:Rule
var activityScenarioRule: ActivityScenarioRule<MainActivity> =
ActivityScenarioRule(MainActivity::class.java)
@Test
fun test_Activity_State() {
// 테스트를 위해 액티비티를 생성해야되는데 activityScenarioRule 사용하면 액티비티를 손쉽게 생성이 가능하다.
val activityState = activityScenarioRule.scenario.state.name
assertThat(activityState).isEqualTo("RESUMED")
}
}
이렇게 간단하게 테스트 코드를 작성하였다.
그러나 위 처럼 할 시 에뮬레이터나 기기 위에서 실행되야 되기 때문에 보시는 것처럼 속도가 느립니다.
이 문제를 개선하기 위해서 개발된 것이 로봇 레트릭입니다.
로봇 레트릭은 Shadow라는 이름으로 안드로이드 SDK의 테스트 더블을 구현을 해주기 때문에 안드로이드 프레임워크를 사용해야 되는 테스트를 JVM 위에서 실행을 할 수가 있습니다. 로보렛트릭을 사용해서 인스트루먼티드 테스트를 수행해 보도록 하겠습니다.
우선은 빌드 그래들에 Dependency를 추가해 줍니다.
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
//...
testImplementation 'org.robolectric:robolectric:4.6.1'
}
이후 로보 레트릭이 적용된 테스트는 Java Virtual Machine 위에서 돌아가는 로컬유닛 테스트가 되기 때문에 테스트 파일을 unit-test 디렉토리에 저장을 해줍니다.
테스트 런너는 robo-retric-test-runner로 지정을 해줍니다.
그러면 아래와 같이 애뮬레이터를 띄우지 않고도 실행이 가능하다.
@RunWith(RobolectricTestRunner::class)
class MainActivityTest {
@Test
@SmallTest
fun test_Activity_State() {
val controller = Robolectric.setupActivity(MainActivity::class.java)
val activityState = controller.lifecycle.currentState.name
assertThat(activityState).isEqualTo("RESUMED")
}
}
그런데 중요한 점은 Robolectric이 4.0으로 버전업 되면서 AndroidX 패키지에 통합이 됐다.
따라서 앞에서 사용한 SetupActivity 같은 3.0까지의 API는 더 이상 사용되지 않고 제거된다.
AndroidX 테스트 API를 사용하면 러블렛트릭 테스트를 사용하든 계측 테스트를 작성하든 상관없이 동일한 안드로이드 개념에 대해 학습할 수 있는 단 하나의 API 세트로 개발자의 인지 부하를 줄일 수 있다.
그림을 보시면 이렇게 로컬 테스트랑 인스트루먼티드 테스트에서 동일한 테스트 코드를 만들고 런너를 JUnit4 런너로 지정을 하면은 이 런너가 알아서 계측 테스트인지 로컬 테스트인지 판단을 한 다음에 계측 테스트라면은 알아서 로봇 레트릭 런너를 적용을 해서 로컬 테스트로 수행을 하고 로컬 테스트는 또 로컬 테스트로 수행을 해주고 하는 식으로 안드로이드 Junit4 Runner가 자동으로 전환을 해주게 된다.
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.*
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
//@RunWith(RobolectricTestRunner::class)
//class MainActivityTest {
//
// @Test
// @SmallTest
// fun test_Activity_State() {
// val controller = Robolectric.setupActivity(MainActivity::class.java)
// val activityState = controller.lifecycle.currentState.name
// assertThat(activityState).isEqualTo("RESUMED")
// }
//}
@RunWith(AndroidJUnit4::class)
@SmallTest
class MainActivityTest {
@get:Rule
var activityScenarioRule: ActivityScenarioRule<MainActivity> =
ActivityScenarioRule(MainActivity::class.java)
@Test
fun test_Activity_State() {
val activityState = activityScenarioRule.scenario.state.name
assertThat(activityState).isEqualTo("RESUMED")
}
}
참고
- 냉동코더의 알기 쉬운 Modern Android Development 입문 (Link)
'Android > Test' 카테고리의 다른 글
Android Test - 2. Local Test (0) | 2024.03.31 |
---|---|
Android Test - 1. Basic (0) | 2024.03.31 |