본문 바로가기

나의 플랫폼/안드로이드

[Android Weekly][#344] 효율적인 LiveData와 ViewModel 테스팅

원본 : https://android.jlelse.eu/effective-livedata-and-viewmodel-testing-17f25069fcd4


Architecture Components 와 그것들을 실행할 방법에 관해 써놓은 글이 많이 있고, 테스트 능력을 향상 시켜줄 혜택 중 하나를 가지고 있다.
자 그럼,  실제로 어떻게 향상시키지? 한번 살펴 보자.



Architecture Components는 Google I/O 2017에서 소개되어 졌고,  그것들은 Android 개발 세계에서 뚜렷한 향상을 의미 했다. 수 년을 걸쳐 익힌 최고의 연습들은 대부분의 공통된 문제들이 바뀌어졌고, 탄탄한 가이드(opinionated guide)를 나오게 했다.

View와 ViewModel은 LiveData를 통하여 연결 한다.

Architecture Components의 주요 고려 사항 중 하나는 공통적으로 경험한 문제들을 다루기 위한 Activity나 Fragment를 변경하기 위한 것이다.

여기서 중요한 부분은 ViewModel에서 모든 로직을 유지하면서, ViewModel에서 사용자 행동들을 즉시 파악하는 것에 대해 View는 수동적으로 남아 있다. 테스트로 검증하기 위한 복잡성은 ViewModel에 가능한한 남겨져 있어야 한다.  우리는 깔끔한 JUnit 테스트를 위해 android.* dependencies를 피해야 한다. 이는 효율적인 ViewModel 테스트를 행하기 위해서 중요하다.

효율적인 ViewModel 테스트

우리는 테스트를 작성하는게 효율적이고 가치 있는 것인지 매번 토론할 수 있었지만, 우리가 원하는 우리의 테스트를 성취하기 위한 몇가지 목표들을 지금 만들어 보자:

  1. 매우 빠른 테스트 실행
  2. 테스트 상의  실제 UseCase를 모델링한  ViewModel
  3. 작성과 유지보수가 쉬운 테스트

첫번째 요구사항을 해결하는 것은 Robolectric 이나 instrumentation test를 사용하지 않고 JUnit만으로 유지하는 것을 의미 한다.  이는 성취하고 잠재적으로 노력할 가치가 있다.

두번째 요구사항을 논의하는 것은 왜 개선된 테스트의 경우 Architecture Components를 따르는 것이 타당한지에 대한 요점을 우리에게 가져다 준다. 컴포넌트들의 분리는 무엇인가를 통해 Activity를 교체하기 쉽게 만든다.  테스트는 ViewModel과 상호작용 하는 실제  UseCase의 테스트 모델링을 유지하는 동안에는 Activity 로써 작동할 수 있다.

이제 쉽게 쓰고 유지하는 마지막 요구사항들을 결정하자. 

효율적인 ViewModel 테스트 작성하기

LiveData과 ViewModel 구성 요소들을 처음 발표하는 동안 기대되는 질문이 'RxJava 아냐?' 였다. 그게 아니다, 하지만 확실하게 몇 가지 공통된 패턴이다.

염두해 두어라,  RxJava는 훌륭하고 매우 잘 테스트된 라이브러리라는 사실과 함께, 우리는  그런 테스팅 접근으로 부터 영감을 받을 수 있다. 각 타입은 멋진 테스트  assertions으로 TestObserver TestSubscriber 을 넘겨주는 (returning)  test() 메소드를 가진다.

우리는 필요한 assert 메소드들을 가지고 우리 자신의 LiveData 를 위한 TestObserver 를 구현 할 수 있고, 우리는  test() 메소드에서 LiveData 를 직접 사용하여 RxJava와 같은 편안함을 얻을 수 있다. livedata-testing 라이브러리를 사용한 코드는 아래와 같다 :

viewModel.counterLiveData()
.test()
.assertHasValue()
.assertValue { it > 3 }
.assertValue(4)
.assertNever { it > 4 }
viewModel.plusButtonClicked() // internally increments counter
viewModel.counterLiveData()
.test()
.assertValue(5)
.assertNever { it > 5}
...

이 구현은   LiveData 를 구독한 simple extension method assertion 메소드들을 도입한 TestObserver를 사용한다 

fun <T> LiveData<T>.test(): TestObserver<T> {  
return TestObserver.test(this)
}

TestObserver 는 자바 클래스이다, 그래서 우리는 심지어 너의 프로젝트에서 Kotlin이 없는 Java만으로도 이러한 접근으로 사용 할 수 있다. static method를 불러야 된다는 것이 유일한 차이점이다:

TestObserver.test(viewModel.counterLiveData())
.assertHasValue()
...;

명심해라 LiveData 를 사용한 모든 테스트들은 현재  android.arch.core:core-testing artifact 의 InstantTaskExecutorRule를 포함해야만 한다. 

이와 같은 테스트 작성이 효율적인가?

지금까지, 이처럼 테스트들을 작성한 것이  So far, writing tests like this fulfilled the goals set:

  1. 테스트는 깔끔한 JUnit 테스트를 사용함으로써 빠르게 실행 된다.
  2. 테스트는 Activity 모델링이므로 그 사용 방식은 기존 Android Code와 동일하다.  

3. TestObserver 와 아마 Kotlin extension methods 를 우리 프로젝트에서 사용하여 Architecture Components 아이디어들을 제대로 구현하는 것이, 우리의 테스트는 빠르게 작성되고 유지하기 쉬워야 한다.

 livedata-testing 라이브러리를 체크하는 것은 어떻게 이와 같이 테스트들을 작성 할지 더 많은 아이디어들과 예제들을 줄것이다. 만약 당신이 시도하고자 결정 하거나 다른 테스팅 접근을 사용한다면, 어떻게 생각하는지 알려 주라. 즐코딩!