#1 이전 글
#1-1 Unit Testing 개요
위 링크에 있는 이전 게시글에 이어서, 실제 안드로이드 프로젝트를 만들어 ViewModel의 Unit Testing을 수행해본다. 본 게시글을 읽기 전에 [Android] Unit Testing - 기초를 보고 오면 이해에 도움이 된다.
#1-2 환경 설정 (build.gradle 등)
이전 게시글의 #3을 토대로 본 게시글에 나오는 안드로이드 프로젝트의 Gradle, AGP, JDK의 버전 설정 및 build.gradle 설정을 진행한다. 이전 게시글의 build.gradle과 달리, 본 게시글에서는 Unit Testing에 사용되지 않는 build.gradle의 plugins { ... }, buildFeatures { ... }, dependencies { ... }의 일부 요소를 제거했다. 이는 코드 다이어트를 위한 개인적인 제거이기 때문에, 이 글은 보는 사람은 제거 없이 그냥 복사 및 붙여넣기해도 된다.
#2 Unit Testing을 적용할 샘플 앱
전체 소스 코드는 본 게시글의 #5에 있다.
#2-1 개요
하나의 액티비티에 하나의 뷰모델로 구성한, 아주 간단한 계산기 앱이다.
#2-2 interface Calculation
interface Calculation {
fun sum(operand1: Int, operand2: Int): Int
fun multiply(operand1: Int, operand2: Int): Int
fun sumAndSquare(operand1: Int, operand2: Int): Int
}
Test double이 상속받아 구현할 인터페이스다.
#2-3 class CalculationViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class CalculationViewModel(private val calculation: Calculation) : ViewModel() {
private val _operand1: MutableLiveData<Int> = MutableLiveData(0)
val operand1: MutableLiveData<Int>
get() = _operand1
private val _operand2: MutableLiveData<Int> = MutableLiveData(0)
val operand2: MutableLiveData<Int>
get() = _operand2
private val _result: MutableLiveData<Int> = MutableLiveData(0)
val result: LiveData<Int>
get() = _result
fun onSumClicked() {
_result.value = calculation.sum(_operand1.value!!, _operand2.value!!)
}
fun onMultiplyClicked() {
_result.value = calculation.multiply(_operand1.value!!, _operand2.value!!)
}
fun onSumAndSquareClicked() {
_result.value = calculation.sumAndSquare(_operand1.value!!, _operand2.value!!)
}
}
변수 operand1 및 operand2는 #2-1에 있는 2개의 EditText와 바인딩된다. 또, 3개의 메소드 또한 #2-1에 있는 3개의 Button과 바인딩되어 해당 버튼이 클릭될 때 실행된다. 마지막으로 result는 결과를 표시할 TextView와 바인딩된다.
#3 Unit Testing
#3-1 간편하게 테스트 클래스를 생성하는 방법
[Android] Unit Testing - 기초 참조. Local unit test 디렉토리에 테스트 클래스를 넣는다.
#3-2 테스트 클래스의 내용 작성
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.google.common.truth.Truth
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito
class CalculationViewModelTest {
/* InstantTaskExecutorRule 규칙(Rule)
* 기본적으로 백그라운드 스레드에서 실행되는 LiveData를 메인 스레드에서 실행되도록 강제함.
* LiveData가 백그라운드 스레드에서 그 값이 변경된다면, 메인 스레드에서 변화를 감지하지 못할 수도 있기 때문.
* 또, 데이터의 변화를 감지하기 전에 테스트가 끝나버릴 여지도 있음.
* 따라서, LiveData가 관여되는 테스트에는 InstantTaskExecutorRule 규칙이 많이 사용됨.
*/
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
private lateinit var calculation: Calculation
private lateinit var calculationViewModel: CalculationViewModel
@Before
fun setUp() {
// Dependency (Test double) 초기화
calculation = Mockito.mock(Calculation::class.java)
Mockito.`when`(calculation.sum(2, 3)).thenReturn(5)
Mockito.`when`(calculation.multiply(5, 4)).thenReturn(20)
Mockito.`when`(calculation.sumAndSquare(4, 7)).thenReturn(121)
// Dependent 초기화
calculationViewModel = CalculationViewModel(calculation)
}
@Test
fun onSumClicked_withOperands2And3_updateLiveData() { // subjectUnderTest_actionOrInput_resultState 규칙으로 함수 명명함
calculationViewModel.operand1.value = 2
calculationViewModel.operand2.value = 3
calculationViewModel.onSumClicked()
val result = calculationViewModel.result.value
Truth.assertThat(result).isEqualTo(/* expected = */ 5)
}
@Test
fun onMultiplyClicked_withOperands5And4_updateLiveData() {
calculationViewModel.operand1.value = 5
calculationViewModel.operand2.value = 4
calculationViewModel.onMultiplyClicked()
val result = calculationViewModel.result.value
Truth.assertThat(result).isEqualTo(/* expected = */ 20)
}
@Test
fun onSumAndSquareClicked_withOperands4And7_updateLiveData() {
calculationViewModel.operand1.value = 4
calculationViewModel.operand2.value = 7
calculationViewModel.onSumAndSquareClicked()
val result = calculationViewModel.result.value
Truth.assertThat(result).isEqualTo(/* expected = */ 121)
}
}
Test double의 일종인 Mock을 생성해주는 Mokito 라이브러리를 이용했다.
#4 작동 확인
#5 완성된 앱
'깨알 개념 > Android' 카테고리의 다른 글
[Android] Unit Testing - Retrofit (0) | 2024.07.08 |
---|---|
[Android] Unit Testing - Room과 LiveData (0) | 2024.07.08 |
[Android] Unit Testing - 기초 (0) | 2024.07.08 |
[Android] Unit Testing - 개요와 환경 설정 (2) | 2024.07.03 |
[Android] Dagger2 - Application 활용하기 (0) | 2024.06.25 |