測試清單和轉接器

1. 事前準備

在先前的程式碼研究室中,我們已說明如何撰寫及執行單元測試和檢測設備測試。這個程式碼研究室介紹了編寫測試時的一些最佳做法,以及如何新增用於測試的特定 Gradle 依附元件。您也會練習撰寫更多單元和檢測設備測試。

必要條件

  • 您已在 Android Studio 中開啟現有專案。
  • 您已在 Android Studio 中撰寫了單元和檢測設備測試。
  • 您已具備在 Android Studio 中瀏覽專案的經驗。
  • 您已具備在 Android Studio 中處理 build.gradle 檔案的經驗。

課程內容

  • 撰寫測試的基本概念。
  • 如何新增測試專用的 Gradle 依附元件。
  • 如何透過檢測設備測試,來測試清單。

軟硬體需求

  • 已安裝 Android Studio 的電腦。
  • Affirmations 應用程式的解決方案程式碼。

下載本程式碼研究室的範例程式碼

在本程式碼研究室中,您將針對 Affirmations 應用程式的解決方案程式碼新增檢測設備測試。

  1. 前往專案所在的 GitHub 存放區頁面。
  2. 驗證分支版本名稱與程式碼研究室中指定的分支版本名稱相符。例如,在下列螢幕截圖中,分支版本名稱為「main」

1e4c0d2c081a8fd2.png

  1. 在專案的 GitHub 頁面中,按一下「Code」按鈕,畫面上會出現彈出式視窗。

1debcf330fd04c7b.png

  1. 在彈出式視窗中,按一下「Download ZIP」按鈕,將專案儲存至電腦。等待下載作業完成。
  2. 在電腦中找到該檔案 (可能位於「下載」資料夾中)。
  3. 按兩下解壓縮 ZIP 檔案。這項操作會建立含有專案檔案的新資料夾。

在 Android Studio 中開啟專案

  1. 啟動 Android Studio。
  2. 在「Welcome to Android Studio」視窗中,按一下「Open」

d8e9dbdeafe9038a.png

注意:如果 Android Studio 已開啟,請改為依序選取「File」>「Open」選單選項。

8d1fda7396afe8e5.png

  1. 在檔案瀏覽器中,前往已解壓縮的專案資料夾所在的位置 (可能位於「Downloads」資料夾中)。
  2. 按兩下該專案資料夾。
  3. 等待 Android Studio 開啟專案。
  4. 按一下「Run」按鈕 8de56cba7583251f.png 即可建構並執行應用程式,請確認應用程式的建構符合預期。

2. 範例應用程式總覽

Affirmations 應用程式是由一個畫面構成,會向使用者顯示搭配確認字詞的圖片清單。

3. 最佳做法

測試程式碼在設計上會與應用程式的商業邏輯有所不同。原因是測試不應包含任何邏輯內容;只單純進行測試而已。因此,測試不應有條件陳述式 (例如 ifwhen),或者控制流程陳述式 (例如 forwhile)。也不得操控值或執行任何實際的運算。

有時候,您的測試可能需要其中一些項目,不過一般而言,請避免使用這些項目。由於我們想要在應用程式中測試這個邏輯類型,因此如果測試中有這類程式碼,可能就會失敗,就像應用程式的程式碼可能會失敗一樣。

我們的單元測試只應從應用程式呼叫部分測試所需的程式碼,並測試呼叫這些程式碼時所產生的程式碼值或狀態。UI 測試則只應測試使用者介面的預期狀態。您可能需要一段時間才能理解這個概念,但沒有關係。我們之後會在程式碼研究室中涵蓋幾個主題,協助說明這個概念。在我們撰寫更多測試的同時,請留意我們撰寫測試的方式。

4. 建立測試目錄

先前的程式碼研究室中,我們已說明如何建立 androidTest 目錄來進行檢測設備測試。針對 androidTest 目錄和 test 目錄,重複這個專案的流程。這兩者的流程相同,唯一的差別是對於 test 目錄,您必須從「New Directory」下拉式選單中選取「test/java」,而不是「androidTest/java」。接著請為每個名稱為 com.example.affirmations 的新目錄建立新套件。

d762ecd8950e97b2.png

5. 建立檢測設備測試類別

在「androidTest」->「com.example.affirmations」路徑中,建立名為 AffirmationsListTests.kt 的新類別。

Dice Roller 應用程式一樣,Affirmations 只有一個活動。為了測試活動的使用者介面,我們必須指明要啟動活動。試試看能不能自己回想出做法!

  1. 在新建的類別中加入測試執行器。
@RunWith(AndroidJUnit4::class)
  1. 為主要活動建立活動情境規則。
@get:Rule
val activity = ActivityScenarioRule(MainActivity::class.java)
  1. Affirmations 應用程式會顯示圖片及各自的正向肯定語錄清單。使用者介面不允許與項目進行任何互動,例如點擊或滑動。因此,這個應用程式的檢測設備測試只會測試靜態資料。建立名為 scroll_to_item() 的測試方法。請記得加上 @Test 的註解。

這項測試應捲動至清單中的特定項目。我們尚未介紹這個方式,因為這需要用到專案尚未參照的方法。在繼續測試之前,需要新增一些測試依附元件。

6. 新增檢測設備測試依附元件

您應該已大致瞭解如何在應用程式的程式碼中,新增要使用的 Gradle 依附元件。透過 Gradle,我們也能新增單元測試和檢測設備測試專用的依附元件。方法是依序前往「app」->「build.gradle」,開啟應用程式層級的 build.gradle 檔案。「依附元件」部分會列出三種實作依附元件的方式:implementationtestImplementationandroidTestImplementation

implementation 適用於應用程式本身會使用的依附元件,testImplementation 適用於單元測試中使用的依附元件,androidTestImplementation 則適用於檢測設備測試中使用的依附元件。

  1. 新增依附元件,允許在檢測設備測試中與 RecyclerView 互動。將下列程式庫新增為 androidTestImplementation
androidx.test.espresso:espresso-contrib:3.4.0

依附元件看起來會像這樣:

dependencies {
    ...
    androidTestImplementation
'androidx.test.espresso:espresso-contrib:3.4.0'
}
  1. 接著同步處理專案。

7. 測試 RecyclerView

  1. 專案同步處理後,請返回 AffirmationsListTests.kt 檔案。提供 ViewInteraction,以使用 onView() 執行動作。onView() 方法需要傳入 ViewMatcher。使用 withId(),確認傳入的是用於確認的 RecyclerView ID。立即在 ViewInteraction 上呼叫 perform()。也就是新加入的依附元件!現在可以傳入 RecyclerViewActions.scrollToPosition<RecyclerView.Viewholder>(9) ViewAction
onView(withId(R.id.recycler_view)).perform(
   RecyclerViewActions
       .scrollToPosition<RecyclerView.ViewHolder>(9)
)

瞭解這一行的語法不太重要,但還是值得看一看。RecyclerViewActions 這個名稱與跟名稱所暗示的一樣:讓您在 RecyclerView 執行測試的類別。scrollToPosition()RecyclerViewActions 類別中的靜態方法,可捲動至指定位置。這個方法會傳回「一般」內容。「一般」內容不在這個程式碼研究室的涵蓋範圍內,但在此案例中,您可以把它想成是 scrollToPosition() 方法,可傳回 RecyclerView 中的所有項目 (可能是任何內容)。

在我們的應用程式中,RecyclerView 中的項目是 ViewHolder,因此我們會在方法呼叫完成後置入一對角括號,並在其中指定 RecyclerView.ViewHolder。最後,請傳遞清單中的最後一個位置 (9)。

  1. 現在已經可以捲動至 RecyclerView 的所需位置,因此請做出斷言,確保 UI 顯示的是預期資訊。確保當您捲動至最後一個項目後,系統會顯示與最終肯定相關聯的文字。請從 ViewInteraction 開始,但這次在新的 ViewMatcher 中傳遞 (在本案例中為 withText())。對於此方法,請傳送包含最後一個肯定語錄文字的字串資源。withText() 方法會根據顯示的文字來識別使用者介面元件。對於這項元件,只需檢查元件中是否顯示所需的文字即可。方法是透過在 ViewInteraction 上呼叫 check()check() 需要 ViewAssertion,因此您可以使用 matches() 方法。最後,傳遞 isDisplayed() 方法,宣告要顯示使用者介面元件。
onView(withText(R.string.affirmation10))
    .check(matches(isDisplayed()))

回到用硬式編碼的方式設定捲動目標位置的附註,有一種方式可透過 RecyclerViewActions 解決此問題。當您不確定清單長度時,可以使用 scrollTo 動作。如要使用 scrollTo 函式,您需要使用 Matcher<View!>! 來尋找特定項目。這可以包含許多項目,但若要達到這項測試的目的,請使用 withText。將其套用到您剛才編寫的測試後,程式碼看起來會像這樣:

onView(withId(R.id.recycler_view)).perform(
   RecyclerViewActions
       .scrollTo<RecyclerView.ViewHolder>(
           withText(R.string.affirmation10)
       )
)

onView(withText(R.string.affirmation10))
    .check(matches(isDisplayed())
)

現在一切已準備就緒,隨時可以執行測試。裝置或模擬器應捲動到清單底部,然後才通過測試。如要確保測試結果正確無誤,請將字串 ID 替換成 R.string.affirmation1。捲動完成後,這個字串資源就不會顯示,且測試應會失敗。

RecyclerViewActions 類別提供的方法有很多種,建議您查看可用的方法

8. 建立本機測試類別

在「test」->「com.example.affirmations」路徑中,建立名為 AffirmationsAdapterTests.kt 的新類別。

9. 新增本機測試依附元件

  1. 在本程式碼研究室的前半部,我們討論了三種依附元件實作方式,且您新增了檢測設備測試的依附元件。現在請新增本機測試的依附元件。方法是依序前往「app」->「build.gradle」,並將以下內容新增為單位測試依附元件:
org.mockito:mockito-core:3.12.4

依附元件應如下所示:

dependencies {
    ...
    testImplementation 'org.mockito:mockito-core:3.12.4'
}
  1. 接著同步處理專案。

10. 測試轉接器

這個應用程式本身不需要進行單元測試,因為沒有足夠的邏輯可以測試。然而,我們可以取得測試各項元件的更多經驗,為日後的測試做準備。

  1. 在單元測試類別中加入以下這行:
private val context = mock(Context::class.java)

mock() 方法來自我們剛才在專案中實作的程式庫。模擬是單元測試的必要部分,但不在這個程式碼研究室的範圍內。我們會在另一個程式碼研究室中詳細說明模擬功能。在 Android 中,Context 是應用程式目前狀態的結構定義,但別忘了,單元測試是在 JVM 執行,而不是在實際裝置上執行,因此沒有 Context。這個模擬方法能讓我們建立 Context 的「模擬」執行個體。這個執行個體沒有任何實際的功能,但可用來測試需要結構定義的方法。

  1. 建立名為 adapter_size() 的函式並加上註解作為測試。這項測試旨在確認轉接器與傳遞至轉接器的清單兩者大小相同。執行方法是建立 ItemAdapter 的執行個體,並傳入 Datasource 類別中 loadAffirmations() 方法所傳回的清單。您也可以建立新的清單並進行測試。如果是單元測試,最佳做法是建立測試專屬的資料,以便我們為這項測試建立自訂名單。
val data = listOf(
   Affirmation(R.string.affirmation1, R.drawable.image1),
   Affirmation(R.string.affirmation2, R.drawable.image2)
)
  1. 立即建立 ItemAdapter 的執行個體,並傳入在上述步驟中建立的 contextdata 變數。
val adapter = ItemAdapter(context, data)

回收器檢視畫面轉接器有一方法,會傳回名為 getItemCount() 的轉接器大小。對於這個應用程式而言,方法如下:

/**
* Return the size of your dataset (invoked by the layout manager)
*/
override fun getItemCount() = dataset.size
  1. 這是應該測試的方法。這個方法的傳回值必須與您在步驟 2 中建立的清單大小相符。使用 assertEquals() 方法,並比較清單大小和轉接器大小的值。
assertEquals("ItemAdapter is not the correct size", data.size, adapter.itemCount)

您已經熟悉 assertEquals() 方法,但建議您仔細檢查這一行。第一個參數是測試失敗時,會在測試結果中顯示的字串。第二個參數是預期的值。第三個參數是實際值。您的測試類別應如下所示:

f81a27f5c1cf055e.png

  1. 立即執行測試!

11. 解決方案程式碼

12. 恭喜

在這個程式碼研究室中,您將進行以下作業:

  • 瞭解如何新增測試專用的依附元件。
  • 瞭解如何透過檢測設備測試與 RecyclerView 互動。
  • 討論用於測試的一些基本最佳做法。