Membuat pengujian unit lokal

Pengujian lokal berjalan langsung di workstation Anda sendiri, bukan di perangkat atau emulator Android. Oleh karena itu, pengujian ini menggunakan Java Virtual Machine (JVM) lokal, bukan perangkat Android untuk menjalankan pengujian. Pengujian lokal memungkinkan Anda mengevaluasi logika aplikasi dengan lebih cepat. Namun, ketidakmampuan untuk berinteraksi dengan framework Android menimbulkan batasan pada jenis pengujian yang dapat Anda jalankan.

Pengujian unit memverifikasi perilaku bagian kecil kode, yaitu unit yang sedang diuji. Hal ini dilakukan dengan mengeksekusi kode tersebut dan memeriksa hasilnya.

Pengujian unit biasanya sederhana, tetapi penyiapannya dapat bermasalah jika unit yang sedang diuji tidak dirancang dengan mempertimbangkan kemampuan pengujian:

  • Kode yang ingin Anda verifikasi harus dapat diakses dari pengujian. Misalnya, Anda tidak dapat menguji metode pribadi secara langsung. Sebagai gantinya, Anda menguji class menggunakan API publiknya.
  • Untuk menjalankan pengujian unit secara terisolasi, dependensi unit yang sedang diuji harus diganti dengan komponen yang Anda kontrol, seperti komponen palsu atau test double lainnya. Hal ini sangat bermasalah jika kode Anda bergantung pada framework Android.

Untuk mempelajari strategi pengujian unit umum di Android, baca Yang perlu diuji.

Lokasi pengujian lokal

Secara default, file sumber untuk pengujian unit lokal ditempatkan di module-name/src/test/. Direktori ini sudah ada saat Anda membuat project baru menggunakan Android Studio.

Menambahkan dependensi pengujian

Anda juga perlu mengonfigurasi dependensi pengujian untuk project agar dapat menggunakan API standar yang disediakan oleh framework pengujian JUnit.

Untuk melakukannya, buka file build.gradle modul aplikasi Anda dan tentukan library berikut sebagai dependensi. Gunakan fungsi testImplementation untuk menunjukkan bahwa dependensi tersebut berlaku untuk set sumber pengujian lokal, dan bukan aplikasi:

dependencies {
  // Required -- JUnit 4 framework
  testImplementation "junit:junit:$jUnitVersion"
  // Optional -- Robolectric environment
  testImplementation "androidx.test:core:$androidXTestVersion"
  // Optional -- Mockito framework
  testImplementation "org.mockito:mockito-core:$mockitoVersion"
  // Optional -- mockito-kotlin
  testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
  // Optional -- Mockk framework
  testImplementation "io.mockk:mockk:$mockkVersion"
}

Membuat class pengujian unit lokal

Anda menulis class pengujian unit lokal sebagai class pengujian JUnit 4.

Untuk melakukannya, buat class yang berisi satu atau beberapa metode pengujian, biasanya di module-name/src/test/. Metode pengujian dimulai dengan anotasi @Test dan berisi kode untuk menjalankan dan memverifikasi satu aspek komponen yang ingin Anda uji.

Contoh berikut menunjukkan cara mengimplementasikan class pengujian unit lokal. Metode pengujian emailValidator_correctEmailSimple_returnsTrue() mencoba memverifikasi isValidEmail(),yang merupakan metode dalam aplikasi. Fungsi pengujian akan menampilkan true jika isValidEmail() juga menampilkan true.

Kotlin

import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

class EmailValidatorTest {
  @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"))
  }

}

Java

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

class EmailValidatorTest {
  @Test
  public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"));
  }
}

Anda harus membuat pengujian yang dapat dibaca yang mengevaluasi apakah komponen dalam aplikasi Anda menampilkan hasil yang diharapkan. Sebaiknya gunakan library pernyataan seperti junit.Assert, Hamcrest, atau Truth. Cuplikan di atas adalah contoh cara menggunakan junit.Assert.

Library Android tiruan

Saat Anda menjalankan pengujian unit lokal, Plugin Android Gradle menyertakan library yang berisi semua API framework Android, yang sesuai dengan versi yang digunakan dalam project Anda. Library ini menyimpan semua metode dan class publik dari API tersebut, tetapi kode di dalam metode telah dihapus. Jika salah satu metode diakses, pengujian akan menampilkan pengecualian.

Hal ini memungkinkan pengujian lokal dibuat saat mereferensikan class dalam framework Android seperti Context. Lebih penting lagi, hal ini memungkinkan Anda menggunakan framework tiruan dengan class Android.

Membuat tiruan dependensi Android

Masalah yang umum terjadi adalah menemukan bahwa suatu class menggunakan resource string. Anda dapat memperoleh resource string dengan memanggil metode getString() di class Context. Namun, pengujian lokal tidak dapat menggunakan Context atau metode apa pun karena metode tersebut termasuk dalam framework Android. Idealnya, panggilan ke getString() akan dipindahkan dari class, tetapi hal ini tidak selalu praktis. Solusinya adalah membuat tiruan atau stub Context yang selalu menampilkan nilai yang sama saat metode getString()-nya dipanggil.

Dengan library Android Mockable dan framework tiruan seperti Mockito atau MockK, Anda dapat memprogram perilaku tiruan class Android dalam pengujian unit.

Untuk menambahkan objek tiruan ke pengujian unit lokal menggunakan Mockito, ikuti model pemrograman ini:

  1. Sertakan dependensi library Mockito dalam file build.gradle, seperti yang dijelaskan dalam Menyiapkan lingkungan pengujian.
  2. Di awal definisi class pengujian unit, tambahkan anotasi @RunWith(MockitoJUnitRunner.class). Anotasi ini memberi tahu runner pengujian Mockito untuk memvalidasi bahwa penggunaan framework Anda sudah benar dan menyederhanakan inisialisasi objek tiruan.
  3. Untuk membuat objek tiruan untuk dependensi Android, tambahkan anotasi @Mock sebelum deklarasi kolom.
  4. Untuk melakukan stub pada perilaku dependensi, Anda dapat menentukan kondisi dan nilai yang ditampilkan saat kondisi terpenuhi menggunakan metode when() dan thenReturn().

Contoh berikut menunjukkan cara membuat pengujian unit yang menggunakan objek Context tiruan di Kotlin yang dibuat dengan Mockito-Kotlin.

import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock

private const val FAKE_STRING = "HELLO WORLD"

@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {

  @Mock
  private lateinit var mockContext: Context

  @Test
  fun readStringFromContext_LocalizedString() {
    // Given a mocked Context injected into the object under test...
    val mockContext = mock<Context> {
        on { getString(R.string.name_label) } doReturn FAKE_STRING
    }

    val myObjectUnderTest = ClassUnderTest(mockContext)

    // ...when the string is returned from the object under test...
    val result: String = myObjectUnderTest.getName()

    // ...then the result should be the expected one.
    assertEquals(result, FAKE_STRING)
  }
}

Untuk mempelajari lebih lanjut cara menggunakan framework Mockito, lihat referensi Mockito API dan class SharedPreferencesHelperTest dalam kode contoh. Coba juga Codelab Pengujian Android.

Error: "Metode ... tidak ditiru"

Library Android Mockable menampilkan pengecualian jika Anda mencoba mengakses salah satu metodenya dengan pesan Error: "Method ... not mocked.

Jika pengecualian yang ditampilkan bermasalah untuk pengujian, Anda dapat mengubah perilaku sehingga metode menampilkan null atau nol, bergantung pada jenis nilai yang ditampilkan. Untuk melakukannya, tambahkan konfigurasi berikut dalam file build.gradle level teratas project Anda di Groovy:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }