# Unit Test - 測試Android Components
---
* 延續上一篇的筆記專案架構 [Unit Test - 基本的單元測試寫法](https://hackmd.io/awJiLPm1Q-KO7D63AC1VAg)
## 這篇會用到Android test,也就是整合測試
* 整合測試會使用到Android Studio的模擬器
* 會使用到@Bdfore 、 @After ..等聲明
## 開始吧
### 情境
* 輸入一個字串,比對context的resource ID是否相同
* 接續上一篇的架構,新增一個類別ResourceComparer

### 試想TDD步驟一: *選定一個功能,新增測試案例*
* 定義函數參數,它需要context, resource ID, 比對的字串
```kotlin=
class ResourceComparer {
//判斷參數的recource ID跟輸入的字串是否相同
fun isEqual(context: Context, resId: Int, string:String): Boolean{
return true
}
}
```
* 新增測試案例
* 這次因為我們要測試的內容是包含Android Compenents,這邊例子是context,所以要把測試程式寫在\app\src\androidTest這個路徑

### 試想TDD步驟二: *執行測試,得到 Failed(紅燈)*
* 這裡我們使用app name來當我們的recource id
```kotlin=
class ResourceComparerTest{
private val resourceComparer = ResourceComparer()
@Test
fun stringResourceNotSameAsGivenString_returnsFalse(){
val context = ApplicationProvider.getApplicationContext<Context>()
val result = resourceComparer.isEqual(context, R.string.app_name,"hello" )
assertThat(result).isFalse()
}
}
```

### 試想TDD步驟三: *實作「夠用」的產品程式*
* 這邊把情境中的條件寫出來
```kotlin=
class ResourceComparer {
fun isEqual(context: Context, resId: Int, string:String): Boolean{
return context.getString(resId) == string
}
}
```
### 試想TDD步驟四: *再次執行測試,得到 Passed(綠燈)*

### 試想TDD步驟五: *重構程式*
* 把測試程式的條件寫完- 當resource ID 跟輸入字串相同
```kotlin=
@Test
fun stringResourceSameAsGivenString_returnsTrue(){
val context = ApplicationProvider.getApplicationContext<Context>()
val result = resourceComparer.isEqual(context, R.string.app_name,"unittesting" )
assertThat(result).isTrue()
}
@Test
fun stringResourceNotSameAsGivenString_returnsFalse(){
val context = ApplicationProvider.getApplicationContext<Context>()
val result = resourceComparer.isEqual(context, R.string.app_name,"hello" )
assertThat(result).isFalse()
}
```

## 優化
* 這個測試程式需要ResourceComparer類別的實例
* 直接宣告一個全域變數來賦予實例是不好的寫法
* 較好的做法是,當個別的測試程式要執行的時候再去產生實例,避免測試程式之間產生干擾,造成測試結果可能不穩定
* 所以Junit提供了@Before 跟 @After聲明可以使用
* @Before就是在@Test的程式要執行之前都會先執行@Before定義的函數
* @After就是在@Test的函數執行完畢之後才執行@After定義的函數,在這邊的例子還用不到。
```kotlin=
private lateinit var resourceComparer :ResourceComparer
// ↓ 這樣寫不好
// private val resourceComparer = ResourceComparer()
@Before
fun setUp(){
//每次執行@Test底下的函數之前都會先產生實例
resourceComparer = ResourceComparer()
}
@After
fun tearDown(){
}
@Test
fun stringResourceSameAsGivenString_returnsTrue() {
val context = ApplicationProvider.getApplicationContext<Context>()
val result = resourceComparer.isEqual(context, R.string.app_name, "unittesting")
assertThat(result).isTrue()
}
@Test
fun stringResourceNotSameAsGivenString_returnsFalse() {
val context = ApplicationProvider.getApplicationContext<Context>()
val result = resourceComparer.isEqual(context, R.string.app_name, "hello")
assertThat(result).isFalse()
}
```
## 補充說明
* 在AndroidTest(整合測試)中,它沒辦法像unitTest可以使用反引號命名函數,例如: `if something returns false`,可能是系統上有什麼考量吧.也許以後可以?
* 整合測試的函數命名,盡量描述清楚
###### tags: `test` `Unit Test` `TDD` `kotlin` `Android`