Codelab ini adalah bagian dari kursus Lanjutan Android di Kotlin. Anda akan mendapatkan manfaat maksimal dari kursus ini jika Anda mengerjakan codelab secara berurutan, tetapi ini tidak wajib. Semua codelab kursus tercantum di halaman landing codelab Android Lanjutan di Kotlin.
Pengantar
Saat menerapkan fitur pertama pada aplikasi pertama, Anda mungkin menjalankan kode untuk memverifikasi bahwa aplikasi berfungsi seperti yang diharapkan. Anda telah melakukan pengujian, meskipun pengujian manual dilakukan. Seiring Anda terus menambahkan dan mengupdate fitur, Anda mungkin juga terus menjalankan kode dan memverifikasi bahwa kode tersebut berfungsi. Namun, melakukannya secara manual setiap kali memang melelahkan, rentan kesalahan, dan tidak menyesuaikan skala.
Komputer sangat bagus untuk penskalaan dan otomatisasi. Jadi, developer di perusahaan besar dan kecil menulis pengujian otomatis, yaitu pengujian yang dijalankan oleh software dan tidak mengharuskan Anda mengoperasikan aplikasi secara manual untuk memverifikasi bahwa kode berfungsi.
Yang akan Anda pelajari dalam rangkaian codelab ini adalah cara membuat kumpulan pengujian (dikenal sebagai suite pengujian) untuk aplikasi dunia nyata.
Codelab pertama ini mencakup dasar-dasar pengujian di Android. Anda akan menulis pengujian pertama dan mempelajari cara menguji LiveData
dan ViewModel
.
Yang harus sudah Anda ketahui
Anda harus memahami:
- Bahasa pemrograman Kotlin
- Library Android Jetpack inti berikut:
ViewModel
danLiveData
- Arsitektur aplikasi, dengan mengikuti pola dari Panduan arsitektur aplikasi dan codelab Dasar-Dasar Android
Yang akan Anda pelajari
Anda akan mempelajari topik berikut:
- Cara menulis dan menjalankan pengujian unit di Android
- Cara menggunakan Pengembangan Berdasarkan Pengujian
- Cara memilih uji instrumentasi dan pengujian lokal
Anda akan mempelajari library dan konsep kode berikut:
Yang akan Anda lakukan
- Menyiapkan, menjalankan, dan menafsirkan pengujian lokal dan berinstrumen di Android.
- Menulis pengujian unit di Android menggunakan JUnit4 dan Matcher.
- Tulis pengujian
LiveData
danViewModel
sederhana.
Dalam serangkaian codelab ini, Anda akan mengerjakan aplikasi Catatan TO-DO. Aplikasi ini memungkinkan Anda menulis tugas untuk diselesaikan dan menampilkannya dalam daftar. Selanjutnya, Anda dapat menandainya sebagai selesai atau tidak, memfilter, atau menghapusnya.
Aplikasi ini ditulis dalam Kotlin, memiliki beberapa layar, menggunakan komponen Jetpack, dan mengikuti arsitektur dari Panduan arsitektur aplikasi. Dengan mempelajari cara menguji aplikasi ini, Anda akan dapat menguji aplikasi yang menggunakan library dan arsitektur yang sama.
Untuk memulai, download kode:
Atau, Anda dapat membuat clone repositori GitHub untuk kode tersebut:
$ git clone https://github.com/googlecodelabs/android-testing.git $ cd android-testing $ git checkout starter_code
Dalam tugas ini, Anda akan menjalankan aplikasi dan menjelajahi code base.
Langkah 1: Jalankan contoh aplikasi
Setelah mendownload aplikasi Daftar Tugas, buka aplikasi di Android Studio dan jalankan. Kode harus dikompilasi. Jelajahi aplikasi dengan melakukan hal berikut:
- Buat tugas baru dengan tombol plus tindakan mengambang. Masukkan judul terlebih dahulu, lalu masukkan informasi tambahan tentang tugas. Simpan dengan FAB centang hijau.
- Dalam daftar tugas, klik judul tugas yang baru saja Anda selesaikan dan lihat layar detail tugas tersebut untuk melihat deskripsi lainnya.
- Dalam daftar atau di layar detail, centang kotak tugas tersebut untuk menetapkan statusnya menjadi Selesai.
- Kembali ke layar tugas, buka menu filter, dan filter tugas berdasarkan status Aktif dan Selesai.
- Buka panel navigasi dan klik Statistik.
- Kembali ke layar ringkasan, dan dari menu panel navigasi, pilih Hapus selesai untuk menghapus semua tugas dengan status Selesai
Langkah 2: Pelajari kode aplikasi contoh
Aplikasi Daftar Tugas didasarkan pada contoh pengujian dan arsitektur Arsitektur Biru yang populer (menggunakan versi arsitektur reaktif dari contoh). Aplikasi mengikuti arsitektur dari Panduan arsitektur aplikasi. Menggunakan ViewModels dengan Fragment, repositori, dan Room. Jika Anda terbiasa dengan salah satu contoh di bawah, aplikasi ini memiliki arsitektur yang serupa:
- Room dengan Codelab View
- Codelab pelatihan Dasar-Dasar Kotlin Android
- Codelab pelatihan Android lanjutan
- Contoh Android Sunflower
- Kursus pelatihan Aplikasi Android dengan Kotlin Udacity
Anda harus memahami arsitektur umum aplikasi daripada memiliki pemahaman mendalam tentang logika di satu lapisan.
Berikut ringkasan paket yang akan Anda temukan:
Paket: | |
| Menambahkan atau mengedit layar tugas: Kode lapisan UI untuk menambahkan atau mengedit tugas. |
| Lapisan data: Hal ini berkaitan dengan lapisan data tugas. Project ini berisi database, jaringan, dan kode repositori. |
| Layar statistik: Kode lapisan UI untuk layar statistik. |
| Layar detail tugas: Kode lapisan UI untuk satu tugas. |
| Layar tugas: Kode lapisan UI untuk daftar semua tugas. |
| Class utilitas: Class bersama yang digunakan di berbagai bagian aplikasi, misalnya untuk tata letak geser ulang yang digunakan di beberapa layar. |
Lapisan data (.data)
Aplikasi ini menyertakan lapisan jaringan yang disimulasikan, dalam paket jarak jauh, dan lapisan database, dalam paket lokal. Untuk mempermudah, dalam project ini lapisan jaringan disimulasikan hanya dengan HashMap
dengan penundaan, daripada membuat permintaan jaringan yang sebenarnya.
Koordinat DefaultTasksRepository
atau memediasi antara lapisan jaringan dan lapisan database serta merupakan yang mengembalikan data ke lapisan UI.
Lapisan UI ( .addedittask, .statistics, .taskdetail, .tasks)
Setiap paket lapisan UI berisi fragmen dan model tampilan, bersama dengan class lain yang diperlukan untuk UI (seperti adaptor untuk daftar tugas). TaskActivity
adalah aktivitas yang berisi semua fragmen.
Navigasi
Navigasi untuk aplikasi dikontrol oleh Komponen navigasi. Hal ini ditentukan dalam file nav_graph.xml
. Navigasi dipicu dalam model tampilan menggunakan class Event
; model tampilan juga menentukan argumen yang akan diteruskan. Fragmen mengamati Event
dan melakukan navigasi sebenarnya di antara layar.
Dalam tugas ini, Anda akan menjalankan pengujian pertama.
- Di Android Studio, buka panel Project, lalu cari tiga folder berikut:
com.example.android.architecture.blueprints.todoapp
com.example.android.architecture.blueprints.todoapp (androidTest)
com.example.android.architecture.blueprints.todoapp (test)
Folder ini dikenal sebagai set sumber. Set sumber adalah folder yang berisi kode sumber untuk aplikasi Anda. Set sumber, yang berwarna hijau (androidTest dan test) berisi pengujian Anda. Saat membuat project Android baru, Anda akan mendapatkan tiga set sumber berikut secara default. Bagian-bagian tersebut adalah:
main
: Berisi kode aplikasi Anda. Kode ini dibagikan di antara semua versi aplikasi lain yang dapat Anda build (dikenal sebagai varian build)androidTest
: Berisi pengujian yang dikenal sebagai pengujian berinstrumen.test
: Berisi pengujian yang dikenal sebagai pengujian lokal.
Perbedaan antara pengujian lokal dan pengujian berinstrumen terletak pada cara menjalankannya.
Pengujian lokal (test
set sumber)
Pengujian ini dijalankan secara lokal di JVM mesin pengembangan dan tidak memerlukan emulator atau perangkat fisik. Oleh karena itu, iklan tersebut berjalan cepat, tetapi fidelitasnya lebih rendah, yang artinya mereka tidak banyak bertindak seperti di dunia nyata.
Dalam Android Studio, pengujian lokal diwakili oleh ikon segitiga hijau dan merah.
Pengujian berinstrumen (androidTest
set sumber)
Pengujian ini berjalan di perangkat Android nyata atau emulasi, sehingga mencerminkan apa yang akan terjadi di dunia nyata, namun juga jauh lebih lambat.
Dalam pengujian berinstrumen Android Studio, hal ini ditunjukkan dengan Android dengan ikon segitiga hijau dan merah.
Langkah 1: Jalankan pengujian lokal
- Buka folder
test
sampai Anda menemukan file ExampleUnitTest.kt. - Klik kanan ruang ini lalu pilih Run ExampleUnitTest.
Anda akan melihat output berikut di jendela Run di bagian bawah layar:
- Perhatikan tanda centang hijau dan perluas hasil pengujian untuk mengonfirmasi bahwa satu pengujian bernama
addition_isCorrect
lulus. Ada baiknya mengetahui bahwa penambahan berfungsi seperti yang diharapkan.
Langkah 2: Buat pengujian gagal
Berikut adalah pengujian yang baru saja Anda jalankan.
ExampleUnitTest.kt
// A test class is just a normal class
class ExampleUnitTest {
// Each test is annotated with @Test (this is a Junit annotation)
@Test
fun addition_isCorrect() {
// Here you are checking that 4 is the same as 2+2
assertEquals(4, 2 + 2)
}
}
Perhatikan bahwa pengujian
- adalah class di salah satu set sumber pengujian.
- berisi fungsi yang dimulai dengan anotasi
@Test
(setiap fungsi adalah pengujian tunggal). - biasanya berisi pernyataan pernyataan.
Android menggunakan library pengujian JUnit untuk pengujian (dalam codelab ini JUnit4). Baik pernyataan maupun anotasi @Test
berasal dari JUnit.
Pernyataan adalah inti dari pengujian. Ini adalah pernyataan kode yang memeriksa apakah kode atau aplikasi Anda berperilaku seperti yang diharapkan. Dalam hal ini, pernyataannya adalah assertEquals(4, 2 + 2)
yang memeriksa bahwa 4 sama dengan 2 + 2.
Untuk melihat seperti apa pengujian yang gagal, tambahkan pernyataan yang dapat Anda lihat dengan mudah akan gagal. Ini akan memeriksa bahwa 3 sama dengan 1+1.
- Tambahkan
assertEquals(3, 1 + 1)
ke pengujianaddition_isCorrect
.
ExampleUnitTest.kt
class ExampleUnitTest {
// Each test is annotated with @Test (this is a Junit annotation)
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
assertEquals(3, 1 + 1) // This should fail
}
}
- Jalankan pengujian.
- Pada hasil pengujian, perhatikan X di samping pengujian.
- Perhatikan juga:
- Satu pernyataan yang gagal akan menggagalkan seluruh pengujian.
- Anda diberi tahu nilai yang diharapkan (3) versus nilai yang benar-benar dihitung (2).
- Anda akan diarahkan ke baris pernyataan
(ExampleUnitTest.kt:16)
yang gagal.
Langkah 3: Jalankan uji instrumentasi
Pengujian berinstrumen ada dalam set sumber androidTest
.
- Buka set sumber
androidTest
. - Jalankan pengujian bernama
ExampleInstrumentedTest
.
ExampleInstrumentedTest
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.android.architecture.blueprints.reactive",
appContext.packageName)
}
}
Tidak seperti pengujian lokal, pengujian ini berjalan pada perangkat (dalam contoh di bawah ponsel Pixel 2 yang diemulasikan):
Jika Anda memiliki perangkat yang terpasang atau emulator yang berjalan, Anda akan melihat pengujian berjalan pada emulator.
Dalam tugas ini, Anda akan menulis pengujian untuk getActiveAndCompleteStats
, yang menghitung persentase statistik tugas aktif dan lengkap untuk aplikasi Anda. Anda dapat melihat angka ini di layar statistik aplikasi.
Langkah 1: Buat class pengujian
- Di set sumber
main
, ditodoapp.statistics
, bukaStatisticsUtils.kt
. - Temukan fungsi
getActiveAndCompletedStats
.
StatistikUtils.kt
internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {
val totalTasks = tasks!!.size
val numberOfActiveTasks = tasks.count { it.isActive }
val activePercent = 100 * numberOfActiveTasks / totalTasks
val completePercent = 100 * (totalTasks - numberOfActiveTasks) / totalTasks
return StatsResult(
activeTasksPercent = activePercent.toFloat(),
completedTasksPercent = completePercent.toFloat()
)
}
data class StatsResult(val activeTasksPercent: Float, val completedTasksPercent: Float)
Fungsi getActiveAndCompletedStats
menerima daftar tugas dan menampilkan StatsResult
. StatsResult
adalah class data yang berisi dua angka, persentase tugas yang selesai, dan persentase yang aktif.
Android Studio menyediakan alat untuk menghasilkan stub pengujian guna membantu Anda menerapkan pengujian untuk fungsi ini.
- Klik kanan
getActiveAndCompletedStats
dan pilih Buat > Uji.
Dialog Create Test akan terbuka:
- Ubah Class name: menjadi
StatisticsUtilsTest
(bukanStatisticsUtilsKtTest
; sebaiknya jangan sertakan KT pada nama class pengujian). - Pertahankan setelan default lainnya. JUnit 4 adalah library pengujian yang sesuai. Paket tujuan sudah benar (mencerminkan lokasi class
StatisticsUtils
) dan Anda tidak perlu mencentang kotak apa pun (ini hanya menghasilkan kode tambahan, tetapi Anda akan menulis pengujian dari awal). - Tekan Oke
Dialog Choose Destination Directory akan terbuka:
Anda akan membuat tes lokal karena fungsi Anda melakukan perhitungan matematika dan tidak akan menyertakan kode khusus Android apa pun. Jadi, Anda tidak perlu menjalankannya di perangkat sungguhan atau yang diemulasikan.
- Pilih direktori
test
(bukanandroidTest
) karena Anda akan menulis pengujian lokal. - Klik OK.
- Perhatikan class
StatisticsUtilsTest
yang dihasilkan dalamtest/statistics/
.
Langkah 2: Tulis fungsi pengujian pertama Anda
Anda akan menulis pengujian yang memeriksa:
- jika tidak ada tugas yang sudah selesai dan satu tugas aktif,
- bahwa persentase pengujian aktif adalah 100%,
- dan persentase tugas yang sudah selesai adalah 0%.
- Buka
StatisticsUtilsTest
. - Buat fungsi dengan nama
getActiveAndCompletedStats_noCompleted_returnsHundredZero
.
StatistikUtilsTest.kt
class StatisticsUtilsTest {
fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
// Create an active task
// Call your function
// Check the result
}
}
- Tambahkan anotasi
@Test
di atas nama fungsi untuk menunjukkan bahwa itu adalah pengujian. - Membuat daftar tugas.
// Create an active task
val tasks = listOf<Task>(
Task("title", "desc", isCompleted = false)
)
- Panggil
getActiveAndCompletedStats
dengan tugas ini.
// Call your function
val result = getActiveAndCompletedStats(tasks)
- Periksa apakah
result
sesuai harapan Anda menggunakan pernyataan.
// Check the result
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)
Kode lengkapnya sebagai berikut.
StatistikUtilsTest.kt
class StatisticsUtilsTest {
@Test
fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
// Create an active task (the false makes this active)
val tasks = listOf<Task>(
Task("title", "desc", isCompleted = false)
)
// Call your function
val result = getActiveAndCompletedStats(tasks)
// Check the result
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)
}
}
- Jalankan pengujian (Klik kanan
StatisticsUtilsTest
, lalu pilih Run).
Kode tersebut harus lulus:
Langkah 3: Tambahkan dependensi AdID
Karena pengujian Anda bertindak sebagai dokumentasi tentang apa yang dilakukan kode Anda, sebaiknya lakukan pengujian yang dapat dibaca manusia. Bandingkan dua pernyataan berikut:
assertEquals(result.completedTasksPercent, 0f)
// versus
assertThat(result.completedTasksPercent, `is`(0f))
Pernyataan kedua membaca lebih seperti kalimat manusia. Ini ditulis menggunakan framework pernyataan yang disebut targetSdkVersion. Alat bagus lainnya untuk menulis pernyataan yang dapat dibaca adalah library Truth. Anda akan menggunakan targetSdkVersion dalam codelab ini untuk menulis pernyataan.
- Buka
build.grade (Module: app)
dan tambahkan dependensi berikut.
app/build.gradle
dependencies {
// Other dependencies
testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
}
Biasanya, Anda menggunakan implementation
saat menambahkan dependensi, tetapi di sini Anda menggunakan testImplementation
. Saat Anda siap membagikan aplikasi kepada dunia, sebaiknya jangan membuat ukuran APK menjadi terlalu besar dengan kode pengujian atau dependensi apa pun dalam aplikasi Anda. Anda dapat menetapkan apakah library harus disertakan dalam kode utama atau pengujian dengan menggunakan konfigurasi gradle. Konfigurasi yang paling umum adalah:
implementation
—Dependensi tersedia di semua set sumber, termasuk set sumber pengujian.testImplementation
—Dependensi hanya tersedia dalam set sumber pengujian.androidTestImplementation
—Dependensi hanya tersedia dalam set sumberandroidTest
.
Konfigurasi yang Anda gunakan akan menentukan tempat dependensi dapat digunakan. Jika Anda menulis:
testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
Artinya, AdID hanya akan tersedia di set sumber pengujian. Ini juga memastikan bahwa targetSdkVersion tidak akan disertakan dalam aplikasi final Anda.
Langkah 4: Gunakan targetSdkVersion untuk menulis pernyataan
- Perbarui pengujian
getActiveAndCompletedStats_noCompleted_returnsHundredZero()
untuk menggunakanassertThat
AdID, bukanassertEquals
.
// REPLACE
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)
// WITH
assertThat(result.activeTasksPercent, `is`(100f))
assertThat(result.completedTasksPercent, `is`(0f))
Perhatikan bahwa Anda dapat menggunakan impor import org.hamcrest.Matchers.`is`
jika diminta.
Pengujian terakhir akan terlihat seperti kode di bawah ini.
StatistikUtilsTest.kt
import com.example.android.architecture.blueprints.todoapp.data.Task
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.`is`
import org.junit.Test
class StatisticsUtilsTest {
@Test
fun getActiveAndCompletedStats_noCompleted_returnsHundredZero {
// Create an active tasks (the false makes this active)
val tasks = listOf<Task>(
Task("title", "desc", isCompleted = false)
)
// Call your function
val result = getActiveAndCompletedStats(tasks)
// Check the result
assertThat(result.activeTasksPercent, `is`(100f))
assertThat(result.completedTasksPercent, `is`(0f))
}
}
- Jalankan pengujian yang diperbarui untuk mengonfirmasi bahwa pengujian masih berfungsi.
Codelab ini tidak akan mengajarkan semua seluk-beluk targetSdkVersion, jadi jika Anda ingin mempelajari lebih lanjut, lihat tutorial resmi.
Ini adalah tugas opsional untuk latihan.
Dalam tugas ini, Anda akan menulis lebih banyak pengujian menggunakan JUnit dan targetSdkVersion. Anda juga akan menulis pengujian menggunakan strategi yang berasal dari praktik program Pengembangan Berdasarkan Pengujian. Pengujian Berdasarkan Pengembangan atau TDD adalah sekolah pemikiran pemrograman yang mengatakan alih-alih menulis kode fitur terlebih dahulu, Anda menulis pengujian terlebih dahulu. Kemudian, Anda menulis kode fitur dengan tujuan untuk lulus pengujian.
Langkah 1. Menulis pengujian
Menulis pengujian saat Anda memiliki daftar tugas normal:
- Jika ada satu tugas yang telah selesai dan tidak ada tugas aktif, persentase
activeTasks
harus0f
, dan persentase tugas yang diselesaikan harus100f
. - Jika ada dua tugas yang telah selesai dan tiga tugas aktif, persentase yang diselesaikan harus
40f
dan persentase aktif harus60f
.
Langkah 2. Menulis pengujian untuk bug
Kode untuk getActiveAndCompletedStats
seperti yang ditulis memiliki bug. Perhatikan bahwa kode tidak menangani dengan benar apa yang terjadi jika daftar kosong atau null. Dalam kedua kasus ini, kedua persentase harus nol.
internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {
val totalTasks = tasks!!.size
val numberOfActiveTasks = tasks.count { it.isActive }
val activePercent = 100 * numberOfActiveTasks / totalTasks
val completePercent = 100 * (totalTasks - numberOfActiveTasks) / totalTasks
return StatsResult(
activeTasksPercent = activePercent.toFloat(),
completedTasksPercent = completePercent.toFloat()
)
}
Untuk memperbaiki kode dan menulis pengujian, Anda harus menggunakan pengembangan yang didorong oleh pengujian. Pengembangan Berdasarkan Pengujian mengikuti langkah-langkah berikut.
- Tulis pengujian, menggunakan struktur yang ditentukan, Kapan, Kemudian, dan dengan nama yang mengikuti konvensi.
- Konfirmasi bahwa pengujian gagal.
- Tulis kode minimal agar pengujian lulus.
- Ulangi untuk semua pengujian!
Alih-alih memulai dengan memperbaiki bug, Anda akan memulai dengan menulis pengujian terlebih dahulu. Selanjutnya, Anda dapat mengonfirmasi bahwa ada pengujian yang melindungi Anda dari bug yang tidak sengaja diperkenalkan kembali di masa mendatang.
- Jika ada daftar yang kosong (
emptyList()
), kedua persentase harus bernilai 0f. - Jika terjadi error saat memuat tugas, daftarnya akan menjadi
null
, dan kedua persentase harus 0f. - Jalankan pengujian dan konfirmasikan bahwa pengujian tersebut gagal:
Langkah 3. Memperbaiki bug
Setelah menjalankan pengujian, perbaiki bug tersebut.
- Perbaiki bug di
getActiveAndCompletedStats
dengan menampilkan0f
jikatasks
adalahnull
atau kosong:
internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {
return if (tasks == null || tasks.isEmpty()) {
StatsResult(0f, 0f)
} else {
val totalTasks = tasks.size
val numberOfActiveTasks = tasks.count { it.isActive }
StatsResult(
activeTasksPercent = 100f * numberOfActiveTasks / tasks.size,
completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size
)
}
}
- Jalankan pengujian lagi dan konfirmasikan bahwa semua pengujian sekarang berhasil.
Dengan mengikuti TDD dan menulis pengujian terlebih dahulu, Anda telah membantu memastikan bahwa:
- Fungsi baru selalu memiliki pengujian terkait; sehingga pengujian Anda bertindak sebagai dokumentasi tentang apa yang dilakukan kode Anda.
- Pengujian Anda memeriksa hasil yang benar dan melindungi dari bug yang telah Anda lihat.
Solusi: Menulis pengujian lainnya
Berikut adalah semua pengujian dan kode fitur yang sesuai.
StatistikUtilsTest.kt
class StatisticsUtilsTest {
@Test
fun getActiveAndCompletedStats_noCompleted_returnsHundredZero {
val tasks = listOf(
Task("title", "desc", isCompleted = false)
)
// When the list of tasks is computed with an active task
val result = getActiveAndCompletedStats(tasks)
// Then the percentages are 100 and 0
assertThat(result.activeTasksPercent, `is`(100f))
assertThat(result.completedTasksPercent, `is`(0f))
}
@Test
fun getActiveAndCompletedStats_noActive_returnsZeroHundred() {
val tasks = listOf(
Task("title", "desc", isCompleted = true)
)
// When the list of tasks is computed with a completed task
val result = getActiveAndCompletedStats(tasks)
// Then the percentages are 0 and 100
assertThat(result.activeTasksPercent, `is`(0f))
assertThat(result.completedTasksPercent, `is`(100f))
}
@Test
fun getActiveAndCompletedStats_both_returnsFortySixty() {
// Given 3 completed tasks and 2 active tasks
val tasks = listOf(
Task("title", "desc", isCompleted = true),
Task("title", "desc", isCompleted = true),
Task("title", "desc", isCompleted = true),
Task("title", "desc", isCompleted = false),
Task("title", "desc", isCompleted = false)
)
// When the list of tasks is computed
val result = getActiveAndCompletedStats(tasks)
// Then the result is 40-60
assertThat(result.activeTasksPercent, `is`(40f))
assertThat(result.completedTasksPercent, `is`(60f))
}
@Test
fun getActiveAndCompletedStats_error_returnsZeros() {
// When there's an error loading stats
val result = getActiveAndCompletedStats(null)
// Both active and completed tasks are 0
assertThat(result.activeTasksPercent, `is`(0f))
assertThat(result.completedTasksPercent, `is`(0f))
}
@Test
fun getActiveAndCompletedStats_empty_returnsZeros() {
// When there are no tasks
val result = getActiveAndCompletedStats(emptyList())
// Both active and completed tasks are 0
assertThat(result.activeTasksPercent, `is`(0f))
assertThat(result.completedTasksPercent, `is`(0f))
}
}
StatistikUtils.kt
internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {
return if (tasks == null || tasks.isEmpty()) {
StatsResult(0f, 0f)
} else {
val totalTasks = tasks.size
val numberOfActiveTasks = tasks.count { it.isActive }
StatsResult(
activeTasksPercent = 100f * numberOfActiveTasks / tasks.size,
completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size
)
}
}
Kerja yang bagus dengan dasar-dasar menulis dan menjalankan pengujian. Berikutnya, Anda akan mempelajari cara menulis pengujian dasar ViewModel
dan LiveData
.
Di codelab lainnya, Anda akan mempelajari cara menulis pengujian untuk dua class Android yang umum di sebagian besar aplikasi—ViewModel
dan LiveData
.
Anda mulai dengan menulis pengujian untuk TasksViewModel
.
Anda akan berfokus pada pengujian yang memiliki semua logika logika dalam model tampilan dan tidak mengandalkan kode repositori. Kode repositori melibatkan kode asinkron, database, dan panggilan jaringan, yang semuanya menambah kerumitan pengujian. Anda akan menghindarinya untuk saat ini dan berfokus pada penulisan pengujian untuk fungsi ViewModel yang tidak langsung menguji apa pun di repositori.
Pengujian yang akan Anda tulis akan memeriksa apakah saat Anda memanggil metode addNewTask
, Event
untuk membuka jendela tugas baru akan diaktifkan. Ini adalah kode aplikasi yang akan Anda uji.
TasksViewModel.kt
fun addNewTask() {
_newTaskEvent.value = Event(Unit)
}
Langkah 1. Membuat class TasksViewModelTest
Dengan mengikuti langkah yang sama seperti yang Anda lakukan untuk StatisticsUtilTest
, dalam langkah ini, Anda akan membuat file pengujian untuk TasksViewModelTest
.
- Buka class yang ingin Anda uji, dalam paket
tasks
,TasksViewModel.
- Dalam kode, klik kanan nama class
TasksViewModel
-> Generate -> Test.
- Di layar Create Test, klik OK untuk menerima (tidak perlu mengubah setelan default apa pun).
- Pada dialog Choose Destination Directory, pilih direktori test.
Langkah 2. Mulai Menulis Pengujian ViewModel Anda
Pada langkah ini, Anda menambahkan pengujian model tampilan untuk menguji bahwa saat Anda memanggil metode addNewTask
, Event
untuk membuka jendela tugas baru diaktifkan.
- Buat pengujian baru yang disebut
addNewTask_setsNewTaskEvent
.
TasksViewModelTest.kt
class TasksViewModelTest {
@Test
fun addNewTask_setsNewTaskEvent() {
// Given a fresh TasksViewModel
// When adding a new task
// Then the new task event is triggered
}
}
Bagaimana dengan konteks aplikasi?
Saat Anda membuat instance TasksViewModel
untuk diuji, konstruktornya memerlukan Konteks Aplikasi. Namun dalam pengujian ini, Anda tidak membuat aplikasi lengkap dengan aktivitas serta UI dan fragmen, jadi bagaimana Anda mendapatkan konteks aplikasi?
TasksViewModelTest.kt
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(???)
Library AndroidX Test menyertakan class dan metode yang memberi Anda versi komponen seperti Aplikasi dan Aktivitas yang dimaksudkan untuk pengujian. Jika Anda memiliki pengujian lokal tempat Anda memerlukan simulasi class framework Android (seperti Konteks Aplikasi), ikuti langkah-langkah berikut untuk menyiapkan AndroidX Test dengan benar:
- Menambahkan dependensi core dan ext Pengujian AndroidX
- Menambahkan dependensi Robolectric Testing library
- Menganotasi class dengan runner pengujian AndroidJunit4
- Menulis kode Pengujian AndroidX
Anda akan menyelesaikan langkah-langkah ini dan kemudian memahami apa yang mereka lakukan bersama.
Langkah 3. Menambahkan dependensi Gradle
- Salin dependensi ini ke dalam file
build.gradle
modul aplikasi Anda untuk menambahkan dependensi inti dan ext inti AndroidX Test, serta dependensi pengujian Robolectric.
app/build.gradle
// AndroidX Test - JVM testing
testImplementation "androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion"
testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"
testImplementation "org.robolectric:robolectric:$robolectricVersion"
Langkah 4. Menambahkan JUnit Test Runner
- Tambahkan
@RunWith(AndroidJUnit4::class)
di atas class pengujian.
TasksViewModelTest.kt
@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
// Test code
}
Langkah 5. Menggunakan AndroidX Test
Pada tahap ini, Anda dapat menggunakan library AndroidX Test. Ini mencakup metode ApplicationProvider.getApplicationContex
t
, yang mendapatkan Konteks Aplikasi.
- Buat
TasksViewModel
menggunakanApplicationProvider.getApplicationContext()
dari library pengujian AndroidX.
TasksViewModelTest.kt
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
- Hubungi
addNewTask
ditasksViewModel
.
TasksViewModelTest.kt
tasksViewModel.addNewTask()
Pada tahap ini, pengujian Anda akan terlihat seperti kode di bawah.
TasksViewModelTest.kt
@Test
fun addNewTask_setsNewTaskEvent() {
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
// When adding a new task
tasksViewModel.addNewTask()
// Then the new task event is triggered
// TODO test LiveData
}
- Jalankan pengujian untuk mengonfirmasi bahwa pengujian berfungsi.
Konsep: Bagaimana cara kerja AndroidX Test?
Apa itu AndroidX Test?
AndroidX Test adalah kumpulan library untuk pengujian. Ini mencakup class dan metode yang memberi Anda versi komponen seperti Aplikasi dan Aktivitas, yang dimaksudkan untuk pengujian. Sebagai contoh, kode yang Anda tulis ini adalah contoh fungsi AndroidX Test untuk mendapatkan konteks aplikasi.
ApplicationProvider.getApplicationContext()
Salah satu manfaat AndroidX Test API adalah dibuat untuk berfungsi baik untuk pengujian lokal dan pengujian berinstrumen. Ini bagus karena:
- Anda dapat menjalankan pengujian yang sama dengan pengujian lokal maupun pengujian berinstrumen.
- Anda tidak perlu mempelajari API pengujian yang berbeda untuk pengujian lokal vs. berinstrumen.
Misalnya, karena Anda menulis kode menggunakan library AndroidX Test, Anda dapat memindahkan class TasksViewModelTest
dari folder test
ke folder androidTest
dan pengujian akan tetap berjalan. getApplicationContext()
bekerja dengan cara yang sedikit berbeda, bergantung pada apakah aplikasi tersebut dijalankan sebagai pengujian lokal atau berinstrumen:
- Jika berupa pengujian berinstrumen, aplikasi akan mendapatkan konteks Aplikasi sebenarnya yang diberikan saat mem-boot emulator atau terhubung ke perangkat sebenarnya.
- Jika merupakan pengujian lokal, pengujian ini menggunakan lingkungan Android simulasi.
Apa itu Robolectric?
Lingkungan Android simulasi yang digunakan AndroidX Test untuk pengujian lokal disediakan oleh Robolectric. Robolectric adalah library yang membuat lingkungan Android simulasi untuk pengujian dan berjalan lebih cepat daripada melakukan booting emulator atau berjalan di perangkat. Tanpa dependensi Robolectric, Anda akan mendapatkan error ini:
Apa fungsi @RunWith(AndroidJUnit4::class)
?
Runner pengujian adalah komponen JUnit yang menjalankan pengujian. Tanpa runner pengujian, pengujian Anda tidak akan berjalan. Ada runner pengujian default yang disediakan oleh JUnit yang Anda dapatkan secara otomatis. @RunWith
menukar runner pengujian default tersebut.
Runner pengujian AndroidJUnit4
memungkinkan AndroidX Test untuk menjalankan pengujian Anda secara berbeda bergantung pada apakah pengujian tersebut merupakan instrumentasi atau pengujian lokal.
Langkah 6. Memperbaiki Peringatan Robolectric
Saat Anda menjalankan kode, perhatikan bahwa Robolectric digunakan.
Karena AndroidX Test dan runner pengujian AndroidJunit4, hal ini dilakukan tanpa Anda menulis satu baris kode Robolectric secara langsung.
Anda mungkin melihat dua peringatan.
No such manifest file: ./AndroidManifest.xml
"WARN: Android SDK 29 requires Java 9..."
Anda dapat memperbaiki peringatan No such manifest file: ./AndroidManifest.xml
dengan memperbarui file gradle.
- Tambahkan baris berikut ke file gradle untuk menggunakan manifes Android yang benar. Opsi includeAndroidResources memungkinkan Anda mengakses resource Android dalam pengujian unit Anda, termasuk file AndroidManifest.
app/build.gradle
// Always show the result of every unit test when running via command line, even if it passes.
testOptions.unitTests {
includeAndroidResources = true
// ...
}
Peringatan "WARN: Android SDK 29 requires Java 9..."
lebih rumit. Menjalankan pengujian di Android Q memerlukan Java 9. Daripada mencoba mengonfigurasi Android Studio untuk menggunakan Java 9, untuk codelab ini, simpan target Anda dan kompilasi SDK pada angka 28.
Ringkasan:
- Pengujian model tampilan murni biasanya dapat dilakukan di set sumber
test
karena kodenya biasanya tidak memerlukan Android. - Anda dapat menggunakan library pengujian AndroidX untuk mendapatkan versi uji komponen seperti Aplikasi dan Aktivitas.
- Jika perlu menjalankan simulasi kode Android di set sumber
test
, Anda dapat menambahkan dependensi Robolectric dan anotasi@RunWith(AndroidJUnit4::class)
.
Selamat, Anda menggunakan library pengujian AndroidX dan Robolectric untuk menjalankan pengujian. Tes Anda belum selesai (Anda belum menulis pernyataan tegas, hanya tertulis // TODO test LiveData
). Anda akan belajar menulis pernyataan tegas dengan LiveData
selanjutnya.
Dalam tugas ini, Anda akan mempelajari cara menyatakan dengan benar nilai LiveData
.
Dari yang terakhir Anda lakukan tanpa melihat pengujian model tampilan, addNewTask_setsNewTaskEvent
.
TasksViewModelTest.kt
@Test
fun addNewTask_setsNewTaskEvent() {
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
// When adding a new task
tasksViewModel.addNewTask()
// Then the new task event is triggered
// TODO test LiveData
}
Untuk menguji LiveData
, Anda disarankan untuk melakukan dua hal:
- Gunakan
InstantTaskExecutorRule
- Memastikan pengamatan
LiveData
Langkah 1. Menggunakan InstantTaskExecutorRule
InstantTaskExecutorRule
adalah Aturan JUnit. Saat Anda menggunakannya dengan anotasi @get:Rule
, beberapa kode di class InstantTaskExecutorRule
akan dijalankan sebelum dan setelah pengujian (untuk melihat kode persisnya, Anda dapat menggunakan pintasan keyboard Command+B untuk melihat file).
Aturan ini menjalankan semua tugas latar belakang yang terkait Komponen Arsitektur dalam thread yang sama sehingga hasil pengujian terjadi secara sinkron, dan dalam urutan yang dapat diulang. Saat Anda menulis pengujian yang menyertakan pengujian LiveData, gunakan aturan ini.
- Tambahkan dependensi gradle untuk library pengujian inti Komponen Arsitektur (yang berisi aturan ini).
app/build.gradle
testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
- Buka
TasksViewModelTest.kt
- Tambahkan
InstantTaskExecutorRule
di dalam classTasksViewModelTest
.
TasksViewModelTest.kt
class TasksViewModelTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
// Other code...
}
Langkah 2. Menambahkan Class LiveDataTestUtil.kt
Langkah Anda berikutnya adalah memastikan LiveData
pengujian yang Anda amati.
Saat menggunakan LiveData
, Anda biasanya memiliki aktivitas atau fragmen (LifecycleOwner
) yang mengamati LiveData
.
viewModel.resultLiveData.observe(fragment, Observer {
// Observer code here
})
Pengamatan ini penting. Anda memerlukan observer aktif di LiveData
untuk
- memicu peristiwa
onChanged
. - memicu Transformasi.
Untuk mendapatkan perilaku LiveData
yang diharapkan untuk LiveData
model tampilan, Anda harus mengamati LiveData
dengan LifecycleOwner
.
Ini menimbulkan masalah: dalam pengujian TasksViewModel
, Anda tidak memiliki aktivitas atau fragmen untuk mengamati LiveData
. Untuk mengatasi hal ini, Anda dapat menggunakan metode observeForever
, yang memastikan LiveData
terus diamati, tanpa memerlukan LifecycleOwner
. Saat observeForever
, Anda perlu ingat untuk menghapus pengamat atau berisiko kebocoran pengamat.
Ini terlihat seperti kode di bawah. Periksa:
@Test
fun addNewTask_setsNewTaskEvent() {
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
// Create observer - no need for it to do anything!
val observer = Observer<Event<Unit>> {}
try {
// Observe the LiveData forever
tasksViewModel.newTaskEvent.observeForever(observer)
// When adding a new task
tasksViewModel.addNewTask()
// Then the new task event is triggered
val value = tasksViewModel.newTaskEvent.value
assertThat(value?.getContentIfNotHandled(), (not(nullValue())))
} finally {
// Whatever happens, don't forget to remove the observer!
tasksViewModel.newTaskEvent.removeObserver(observer)
}
}
Banyak kode boilerplate untuk mengamati satu LiveData
dalam pengujian. Ada beberapa cara untuk menghapus boilerplate ini. Anda akan membuat fungsi ekstensi yang disebut LiveDataTestUtil
untuk mempermudah penambahan observer.
- Buat file Kotlin baru bernama
LiveDataTestUtil.kt
di set sumbertest
Anda.
- Salin dan tempel kode di bawah.
LiveDataTestUtil.kt
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun <T> LiveData<T>.getOrAwaitValue(
time: Long = 2,
timeUnit: TimeUnit = TimeUnit.SECONDS,
afterObserve: () -> Unit = {}
): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data = o
latch.countDown()
this@getOrAwaitValue.removeObserver(this)
}
}
this.observeForever(observer)
try {
afterObserve.invoke()
// Don't wait indefinitely if the LiveData is not set.
if (!latch.await(time, timeUnit)) {
throw TimeoutException("LiveData value was never set.")
}
} finally {
this.removeObserver(observer)
}
@Suppress("UNCHECKED_CAST")
return data as T
}
Ini adalah metode yang cukup rumit. Fungsi ini membuat fungsi ekstensi Kotlin bernama getOrAwaitValue
yang menambahkan observer, mendapatkan nilai LiveData
, lalu membersihkan observer—pada dasarnya, versi singkat yang dapat digunakan kembali dari kode observeForever
yang ditunjukkan di atas. Untuk penjelasan lengkap tentang kelas ini, lihat postingan blog ini.
Langkah 3. Menggunakan getOrAwaitValue untuk menulis pernyataan
Pada langkah ini, Anda menggunakan metode getOrAwaitValue
dan menulis pernyataan tegas yang memeriksa bahwa newTaskEvent
dipicu.
- Dapatkan nilai
LiveData
untuknewTaskEvent
menggunakangetOrAwaitValue
.
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
- Nyatakan bahwa nilainya bukan null.
assertThat(value.getContentIfNotHandled(), (not(nullValue())))
Pengujian lengkap akan terlihat seperti kode di bawah ini.
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.android.architecture.blueprints.todoapp.getOrAwaitValue
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.not
import org.hamcrest.Matchers.nullValue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@Test
fun addNewTask_setsNewTaskEvent() {
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
// When adding a new task
tasksViewModel.addNewTask()
// Then the new task event is triggered
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
assertThat(value.getContentIfNotHandled(), not(nullValue()))
}
}
- Jalankan kode dan tonton ujiannya.
Setelah melihat cara menulis pengujian, tulis pengujian Anda sendiri. Pada langkah ini, dengan menggunakan keterampilan yang telah Anda pelajari, latih menulis pengujian TasksViewModel
lainnya.
Langkah 1. Menulis pengujian ViewModel Anda sendiri
Anda akan menulis setFilterAllTasks_tasksAddViewVisible()
. Pengujian ini harus memeriksa bahwa jika Anda telah menetapkan jenis filter untuk menampilkan semua tugas, tombol Tambahkan tugas akan terlihat.
- Dengan menggunakan
addNewTask_setsNewTaskEvent()
sebagai referensi, tulis pengujian dalamTasksViewModelTest
yang disebutsetFilterAllTasks_tasksAddViewVisible()
yang menetapkan mode pemfilteran keALL_TASKS
dan menegaskan bahwa LiveDatatasksAddViewVisible
adalahtrue
.
Gunakan kode di bawah untuk memulai.
TasksViewModelTest
@Test
fun setFilterAllTasks_tasksAddViewVisible() {
// Given a fresh ViewModel
// When the filter type is ALL_TASKS
// Then the "Add task" action is visible
}
Catatan:
- Enum
TasksFilterType
untuk semua tugas adalahALL_TASKS.
- Visibilitas tombol untuk menambahkan tugas dikontrol oleh
LiveData
tasksAddViewVisible.
- Jalankan pengujian Anda.
Langkah 2. Bandingkan pengujian Anda dengan solusinya
Bandingkan solusi Anda dengan solusi di bawah ini.
TasksViewModelTest
@Test
fun setFilterAllTasks_tasksAddViewVisible() {
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
// When the filter type is ALL_TASKS
tasksViewModel.setFiltering(TasksFilterType.ALL_TASKS)
// Then the "Add task" action is visible
assertThat(tasksViewModel.tasksAddViewVisible.getOrAwaitValue(), `is`(true))
}
Periksa apakah Anda melakukan hal berikut:
- Anda membuat
tasksViewModel
menggunakan pernyataanApplicationProvider.getApplicationContext()
AndroidX yang sama. - Anda memanggil metode
setFiltering
, dengan meneruskan enum jenis filterALL_TASKS
. - Anda memastikan bahwa
tasksAddViewVisible
benar, menggunakan metodegetOrAwaitNextValue
.
Langkah 3. Tambahkan aturan @Before
Perhatikan bagaimana Anda menentukan TasksViewModel
di awal kedua pengujian.
TasksViewModelTest
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
Jika memiliki kode penyiapan berulang untuk beberapa pengujian, Anda dapat menggunakan anotasi @Before untuk membuat metode penyiapan dan menghapus kode berulang. Karena semua pengujian ini akan menguji TasksViewModel
, dan memerlukan model tampilan, pindahkan kode ini ke blok @Before
.
- Buat variabel instance
lateinit
bernamatasksViewModel|
. - Buat metode yang disebut
setupViewModel
. - Anotasikan dengan
@Before
. - Pindahkan kode pembuatan instance model ke
setupViewModel
.
TasksViewModelTest
// Subject under test
private lateinit var tasksViewModel: TasksViewModel
@Before
fun setupViewModel() {
tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
}
- Jalankan kode!
Peringatan
Jangan lakukan hal berikut, jangan melakukan inisialisasi
tasksViewModel
dengan definisinya:
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
Tindakan ini akan menyebabkan instance yang sama digunakan untuk semua pengujian. Ini adalah hal yang harus Anda hindari karena setiap pengujian harus memiliki instance baru dari subjek yang sedang diuji (ViewModel dalam kasus ini).
Kode final untuk TasksViewModelTest
akan terlihat seperti kode di bawah ini.
TasksViewModelTest
@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
// Subject under test
private lateinit var tasksViewModel: TasksViewModel
// Executes each task synchronously using Architecture Components.
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@Before
fun setupViewModel() {
tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
}
@Test
fun addNewTask_setsNewTaskEvent() {
// When adding a new task
tasksViewModel.addNewTask()
// Then the new task event is triggered
val value = tasksViewModel.newTaskEvent.awaitNextValue()
assertThat(
value?.getContentIfNotHandled(), (not(nullValue()))
)
}
@Test
fun getTasksAddViewVisible() {
// When the filter type is ALL_TASKS
tasksViewModel.setFiltering(TasksFilterType.ALL_TASKS)
// Then the "Add task" action is visible
assertThat(tasksViewModel.tasksAddViewVisible.awaitNextValue(), `is`(true))
}
}
Klik di sini untuk melihat perbedaan antara kode yang Anda mulai dan kode akhir.
Untuk mendownload kode codelab yang sudah selesai, Anda dapat menggunakan perintah git di bawah:
$ git clone https://github.com/googlecodelabs/android-testing.git $ cd android-testing $ git checkout end_codelab_1
Atau, Anda dapat mendownload repositori sebagai file Zip, mengekstraknya, dan membukanya di Android Studio.
Codelab ini membahas:
- Cara menjalankan pengujian dari Android Studio.
- Perbedaan antara uji lokal (
test
) dan instrumentasi (androidTest
). - Cara menulis pengujian unit lokal menggunakan JUnit dan audiens.
- Menyiapkan pengujian ViewModel dengan Library Pengujian AndroidX.
Kursus Udacity:
Dokumentasi developer Android:
- Panduan untuk arsitektur aplikasi
- JUnit4
- ID iklan
- Library Pengujian Robolectric
- Library Pengujian AndroidX
- Library Pengujian Inti Komponen Arsitektur AndroidX
- set sumber
- Menguji dari command line
Video:
Lainnya:
Untuk link ke codelab lainnya dalam kursus ini, lihat halaman landing codelab Android Lanjutan di Kotlin.