#1 ์ด์ ๊ธ
#1-1 Unit Testing ๊ฐ์
[Android] Unit Testing - ๊ฐ์์ ํ๊ฒฝ ์ค์
#1 ์๋๋ก์ด๋ ์ฑ ํ ์คํธ#1-1 ์๋๋ก์ด๋ ์ฑ ํ ์คํธ์ ์ข ๋ฅ๋จผ์ , ์ฌ๊ธฐ์ ์๋ ๊ตฌ๊ธ ๊ณต์ ๋ฌธ์์์ ์๋๋ก์ด๋ ์ฑ ํ ์คํธ์ ๋ํ ๊ฐ์๋ฅผ ์ฝ์ผ๋ฉด ์ข๋ค. ํด๋น ๊ตฌ๊ธ ๊ณต์ ๋ฌธ์์์ ๋ณต์ฌํด์จ ์์ ๊ทธ๋ฆผ
kenel.tistory.com
์ ๋งํฌ์ ์๋ ์ด์ ๊ฒ์๊ธ์ ์ด์ด์, ์ค์ ์๋๋ก์ด๋ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด 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-practice/unit-test/TestingViewModel at master · Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Unit Testing - Retrofit (0) | 2024.07.08 |
---|---|
[Android] Unit Testing - Room๊ณผ LiveData (1) | 2024.07.08 |
[Android] Unit Testing - ๊ธฐ์ด (0) | 2024.07.08 |
[Android] Unit Testing - ๊ฐ์์ ํ๊ฒฝ ์ค์ (2) | 2024.07.03 |
[Android] Dagger2 - Application ํ์ฉํ๊ธฐ (0) | 2024.06.25 |