-
Tests App on Android(2) - RobolectricAndroid 2021. 7. 1. 08:35
Robolectric은 먼저 Gradle을 권장하고 (Android Studio에서 선택한 빌드 시스템이므로) 두 번째로 Bazel을 권장한다.
Robolectric은 Android Studio 및 Android Gradle 플러그인 3.2.1 이상에서 가장 잘 작동한다.
build.gradle 파일에 다음을 추가한다.
android { testOptions { unitTests { includeAndroidResources = true } } } dependencies { testImplementation 'org.robolectric:robolectric:4.4' }
Android 스튜디오 3.3 미만에서는 gradle.properties에 다음 줄을 추가한다
android.enableUnitTestBinaryResources=true
참고로 AndroidJUnit4 클래스는 androidx.test.ext 패키지에 있기에 이 모듈을 build.gradle에 추가해줘야 한다. (androidx.test.runner 패키지에 있는 AndroidJUnit4 클래스는 deprecated 되었다.)
androidTestImplementation 'androidx.test.ext:junit:$version'
android api 29 version issue
Robolectric은 안드로이드 API 버전 테스트에 대해서 Java9 버전 이상을 요구한다.
- [File] -> [Project Structures]의 SDK Location에서 JDK를 Java9로 변경하거나
- @Config 테스트 환경을 API 버전을 29미만으로 설정
예 : @Config(sdk = [Build.VERSION_CODES.P])
AndroidX Test
Robolectric은 버전 4.0 이후 Android의 공식 테스트 라이브러리와 완벽하게 호환되도록 설계되었다. 이제 Robolectric 테스트에서 AndroidX test runner를 사용할 수 있다.
로그 출력
@Before fun setUp(){ ShadowLog.stream = System.out }
디바이스에서 로그를 출력하는 코드를 JVM에서도 동작하게 만드는 것으로 이렇게 설정하지 않으면 Log.d()는 로그를 출력하지 않는다.
TestRunner
Robolectric Test 에서는 자체적으로 RobolectricTestRunner 를 제공하고 있지만, AndroidX Test API 에 포함되어 있는 AndroidJUnit4 클래스와도 호환된다.
Robolectric
@RunWith(RobolectricTestRunner::class) public class ExampleUnitTest { }
AndroidX Test
@RunWith(AndroidJUnit4::class) class ExampleInstrumentedTest { }
Application
AndroidX Test
@Before fun setUp() { val app = ApplicationProvider.getApplicationContext<Context>() }
Activities
Robolectric은 Robolectric.buildActivity()를 제공하여 개발자가 활동 라이프 사이클을 단계별로 진행할 수있는 ActivityController를 반환한다. ActivityController를 잘 다루기 위해서는 Lifecycle에 대한 정확한 이해가 필요하다.
ActivityController는 활동의 수명주기를 제어하기위한 low-level API를 제공한다. 테스트에서 직접 ActivityController를 사용하는 것은 권장되지 않는다. Android 프레임 워크와 동일한 방식으로 모든 수명주기 콜백 메서드 (create, postCreate, start,…)를 직접 호출해야한다.
대신 androidx.test.core.app.ActivityScenario를 사용하는 것이 좋다. Androidx.test.core.app.ActivityScenario는 수명주기를 제어하기 위해 더 높은 수준의 간소화 된 API를 제공하며 계측 테스트에서도 작동한다.
Instrumentation test에서는 @Rule 어노테이션에 사용할 수 있는 ActivityScenarioRule 클래스도 있다.
@Test fun testIntent(){ //Given val intent = Intent() val controller:ActivityController<MainActivity> = Robolectric .buildActivity(MainActivity::class.java, intent) .setup() //When controller.pause().stop() //Then assertEquals(controller.intent, intent) }
Views
Robolectric은 View 상호작용을 위한 매우 제한된 API를 가지고 있다. Robolectric 4.0 이후로 Espresso API가 지원된다.
AndroidX Test
@Test fun inputText(){ //GIVEN val scenario = ActivityScenario.launch(MainActivity::class.java) val helloStr = "Hello, World" //WHEN scenario.moveToState(Lifecycle.State.CREATED) //THEN scenario.onActivity { val textView = it.findViewById<TextView>(R.id.helloTextView) textView.setText(helloStr) assertEquals(textView.text.toString(), helloStr) } }
Button
@Test fun textView_when_click_button(){ val controller:ActivityController<MainActivity> = Robolectric.buildActivity(MainActivity::class.java) val activity = controller .create() .start() .resume() .visible() .get() activity.mainButton.performClick() assertEquals("Hello World", activity.mainTextView.text) }
다국어 테스트
@Config annotation에 qualifiers로 locale을 설정할 수 있다.
@Test @Config(qualifiers = "en") fun localizedEnglishHello() { val controller:ActivityController<MainActivity> = Robolectric.buildActivity(MainActivity::class.java) val activity = controller .create() .start() .resume() .visible() .get() assertEquals(activity.helloTextView.text.toString(), "Hello") } @Test @Config(qualifiers="ko") fun localizedKoreanHello() { val controller:ActivityController<MainActivity> = Robolectric.buildActivity(MainActivity::class.java) val activity = controller .create() .start() .resume() .visible() .get() assertEquals(activity.helloTextView.text.toString(), "안녕하세요") }
References
'Android' 카테고리의 다른 글
ANR(Application Not Responding) (0) 2021.07.19 ViewPager2 (0) 2021.07.10 Tests App on Android(1) (0) 2021.06.28 Room Database (0) 2021.06.14 ConstraintLayout(2) (0) 2021.06.13