news

Senin, 15 Juni 2020

Belajar Aplikasi Android : Pengujian ViewModel dalam Proyek Academy


Tujuan

Pada Codelab kali ini Anda akan mempelajari bagaimana menguji ViewModel dalam proyek Academy dengan Unit Test dan Instrumental Test.

Logika Dasar

Unit Testing: Melakukan pengujian tiap ViewModel
Instrumental Testing: Melakukan pengujian tiap halaman dan keseluruhan Aplikasi.

Codelab Unit Testing ViewModel

  1. Bukalah proyek Academy yang sudah Anda buat pada modul sebelumnya atau Anda bisa unduh di sini:
  2. Pertama yang perlu dilakukan adalah menuliskan skenario testing yang dilakukan:
    • AcademyViewModelTest:
      • Memuat Courses:
        • Memastikan data course tidak null.
        • Memastikan jumlah data course sesuai dengan yang diharapkan.
    • BookmarkViewModelTest:
      • Memuat Bookmarks:
        • Memastikan data course tidak null.
        • Memastikan jumlah data course sesuai dengan yang diharapkan.
    • DetailCourseViewModelTest:
      • Memuat Course:
        • Memastikan data course tidak null.
        • Memastikan data course sesuai dengan yang diharapkan.
      • Memuat Modules:
        • Memastikan data module tidak null.
        • Memastikan jumlah data module sesuai dengan yang diharapkan.
    • CourseReaderViewModelTest:
      • Memuat Modules:
        • Memastikan data module tidak null.
        • Memastikan jumlah data module sesuai dengan yang diharapkan.
      • Memuat Module yang dipilih:
        • Memastikan data module tidak null.
        • Memastikan data content tidak null.
        • Memastikan value dari content tidak null.
        • Memastikan data content sesuai dengan yang diharapkan.
  3. Bukalah AcademyViewModel, kemudian klik ALT + Enter di bagian AcademyViewModel seperti ini:
    Kotlin
    20191218144310e2ed20653c08886f5e2e9f821ca98084.png
    Java
    RUSSaAYr-Z-C-QQYhrFH0wTVTRlqRa1r2jeN4FOf4XGwR3BVBtAaGtP651ppPf-TyP1W6WMF3os8si6gKVkCp0zU5Tc6DGgAaovO1O8KyISE5q20YpqIOJa9o0a7hjA5DCmtQPmo
    Kemudian pilih Create Test, maka akan muncul tampilan seperti ini:
    201912181444027710e0c66fcaa95193459e07c0746ee3.png
    Biarkan nama default seperti tampilan di atas, kemudian tekan tombol OK maka akan muncul pilihan tujuan pembuatan kelas. Karena Anda akan melakukan Unit Testing, maka pilih folder test.
    r6oMKyQAvaXpJ2-ADRNd6u4lixXneiJ6DgsCRw1j7eSdSZAPp9H33d0w8O98ljqp2Cwd7piXALNTwbl69KO8px3hJc6i99aBX65L9hc-WQcQugMVBffgWKkZEjlg4Cu_egeFCdJ_
    Tekan tombol OK maka secara otomatis akan ada sebuah kelas baru dengan nama AcademyViewModelTesting.
    PAor91YkvsbVRhVI4ENOYtJojYkHB0ljyzihpT1w9hnDvwu1lK68hSPCknia5UvNDJml5DlLkxqTxcNhMQeQuXrjTeuHA9JPWvpJzLdJoWvz-rROsID7728R0LeHNVSgDOeSDM44
    Catatan:Hapuslah ExampleUnitTest, karena kita tidak akan memakai kelas tersebut.
  4. Selanjutnya, bukalah kelas AcademyViewModelTest. Ujilah metode getCourses() dengan memasukkan kode berikut:
    Kotlin
    class AcademyViewModelTest {

    private lateinit var viewModel: AcademyViewModel

    @Before
    fun setUp() {
    viewModel = AcademyViewModel()
    }


    @Test
    fun getCourses() {
    val courseEntities = viewModel.getCourses()
    assertNotNull(courseEntities)
    assertEquals(5, courseEntities.size)

    }
    }
    Java
    public class AcademyViewModelTest {
    private AcademyViewModel viewModel;

    @Before
    public void setUp() {
    viewModel = new AcademyViewModel();
    }


    @Test
    public void getCourses() {
    List<CourseEntity> courseEntities = viewModel.getCourses();
    assertNotNull(courseEntities);
    assertEquals(5, courseEntities.size());

    }
    }
  1. Jalankan pengujian pada kelas AcademyViewModelTest, dengan cara menekan tombol di sebelah kiri kode editor.
    BOaUoXng6TmSnfjxTq8Eif51eYqs1VAJJRrRtTuHjWhxr6j8wbbUU2lGQIfaXvyQGWf2Z7wXrk_3uQxKbj6QrghpMG7SweYRT90GmziKLTvEixTk4OCFdUASdNKzMwTlC-OC0JIL
    Pilihlah Run ‘AcademyViewModelTest’, maka hasil pengujiannya jadi seperti ini:
    YmY0Wb59Y1Qq4pv7tGWpMODcP6n0svzGoIHClq2sQiCrK4hjW6jozFigCTb5aN3RFF9tsnX3eGU9bj3cUDsMLDY4flz72bjnhIbPQJj_Q48-7TD84NTfsZLMtAxv7l5MZO4gTjkb
    Selamat, Anda berhasil menguji AcademyViewModel dengan cara membandingkan ukuran dari array viewModel.getCourses().
  2. Lakukanlah kembali langkah nomor 2 untuk melakukan Unit Testing kelas BookmarkViewModel, DetailCoursesViewModel dan CourseReaderViewModel. Jika Anda sudah melakukan langkah tersebut, maka tampilan kelas pada package test akan jadi seperti ini:
    Cdfzbz0JuUmneBD7Q1mUW775EPwNBtgucdfQToi9rUT-1pVxtyV8FT48Il0Ukoh7Mmh0-1ulJ-ADoGTKfJGztX9HGPY1OgIjQ7rjfF0U9WMxYn8pDJ0nNhJ5IYZS-kwh03WxB0Gy
  3. Bukalah BookmarkViewModelTest, kita akan menguji apakah metode getBookmark sudah benar atau belum. Tambahkan kode berikut:
    Kotlin
    class BookmarkViewModelTest {
    private lateinit var viewModel: BookmarkViewModel

    @Before
    fun setUp() {
    viewModel = BookmarkViewModel()
    }

    @Test
    fun getBookmark() {
    val courseEntities = viewModel.getBookmarks()
    assertNotNull(courseEntities)
    assertEquals(5, courseEntities.size)
    }
    }
    Java
    public class BookmarkViewModelTest {
    private BookmarkViewModel viewModel;

    @Before
    public void setUp() {
    viewModel = new BookmarkViewModel();
    }

    @Test
    public void getBookmark() {
    List<CourseEntity> courseEntities = viewModel.getBookmarks();
    assertNotNull(courseEntities);
    assertEquals(5, courseEntities.size());
    }
    }
    Jika dilihat dari kode di atas, cara pengujian yang dilakukan sama karena data bookmark sama-sama berasal dari kelas DataDummy. Jalankan pengujian tersebut, maka akan jadi seperti ini:
    Qy78LBYP6WNW2lnmxFmOVl7oKkqQtcdHIOcvi116R8Xzc1YxWQU0gkLyo8Ni1xqsxZ7OqYGBlpgrijlLzTrNTKiath5cyLN-zYUic4Pu92HgTk9d-l8v6nj6rO0JSlG3RAxpbiXk
    Sekali lagi, selamat! Anda berhasil melakukan pengujian BookmarkViewModel dengan unit testing. Tapi masih ada 2 kelas ViewModel lagi yang perlu diuji.
  4. Bukalah kelas DetailCourseViewModelTest. Pada kelas ini, terdapat 2 metode sumber data yakni getCourse() dan getModules(). Tambahkan kode berikut untuk melakukan pengujian terhadap 2 metode tersebut:
    Kotlin
    class DetailCourseViewModelTest {
    private lateinit var viewModel: DetailCourseViewModel
    private val dummyCourse = DataDummy.generateDummyCourses()[0]
    private val courseId = dummyCourse.courseId

    @Before
    fun setUp() {
    viewModel = DetailCourseViewModel()
    viewModel.setSelectedCourse(courseId)
    }

    @Test
    fun getCourse() {
    viewModel.setSelectedCourse(dummyCourse.courseId)
    val courseEntity = viewModel.getCourse()
    assertNotNull(courseEntity)
    assertEquals(dummyCourse.courseId, courseEntity.courseId)
    assertEquals(dummyCourse.deadline, courseEntity.deadline)
    assertEquals(dummyCourse.description, courseEntity.description)
    assertEquals(dummyCourse.imagePath, courseEntity.imagePath)
    assertEquals(dummyCourse.title, courseEntity.title)
    }

    @Test
    fun getModules() {
    val moduleEntities = viewModel.getModules()
    assertNotNull(moduleEntities)
    assertEquals(7, moduleEntities.size.toLong())
    }
    }
    Java
    public class DetailCourseViewModelTest {
    private DetailCourseViewModel viewModel;
    private CourseEntity dummyCourse = DataDummy.generateDummyCourses().get(0);
    private String courseId = dummyCourse.getCourseId();

    @Before
    public void setUp() {
    viewModel = new DetailCourseViewModel();
    viewModel.setSelectedCourse(courseId);
    }

    @Test
    public void getCourse() {
    viewModel.setSelectedCourse(dummyCourse.getCourseId());
    CourseEntity courseEntity = viewModel.getCourse();
    assertNotNull(courseEntity);
    assertEquals(dummyCourse.getCourseId(), courseEntity.getCourseId());
    assertEquals(dummyCourse.getDeadline(), courseEntity.getDeadline());
    assertEquals(dummyCourse.getDescription(), courseEntity.getDescription());
    assertEquals(dummyCourse.getImagePath(), courseEntity.getImagePath());
    assertEquals(dummyCourse.getTitle(), courseEntity.getTitle());
    }

    @Test
    public void getModules() {
    List<ModuleEntity> moduleEntities = viewModel.getModules();
    assertNotNull(moduleEntities);
    assertEquals(7, moduleEntities.size());
    }
    }
    Jalankan pengujian pada kelas tersebut, maka hasil pengujiannya jadi seperti ini:
    OGj5E_jgkh6WYf7xt0Mfko-Ia0PShBPh8G7jo3BeaLDkCHL2BZ3H6ov4OvM1248VYtiqN6jmYaS1trXX6moOFumYX5Lq16qgkf0J3y8KBJXx8dEZp-euFusEOCUOK2x-OjbP48Vi
    Selamat, Anda juga berhasil menguji DetailCourseViewModel dengan cara membandingkan ukuran dari array viewModel.getModules() dan membandingkan data CourseEntity hasil dari viewModel.getCourses().
  1. Terakhir, bukalah CourseReaderViewModelTest. Pada kelas CourseReaderViewModel, terdapat 2 metode yang harus diuji yakni getSelectedModule dan getModules. Tambahkan kode berikut untuk melakukan pengujian:
    Kotlin
    class CourseReaderViewModelTest {

    private lateinit var viewModel: CourseReaderViewModel

    private val dummyCourse = DataDummy.generateDummyCourses()[0]
    private val courseId = dummyCourse.courseId
    private val dummyModules = DataDummy.generateDummyModules(courseId)
    private val moduleId = dummyModules[0].moduleId

    @Before
    fun setUp() {
    viewModel = CourseReaderViewModel()
    viewModel.setSelectedCourse(courseId)
    viewModel.setSelectedModule(moduleId)

    val dummyModule = dummyModules[0]
    dummyModule.contentEntity = ContentEntity("<h3 class=\\\"fr-text-bordered\\\">"+dummyModule.title+"</h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>")
    }

    @Test
    fun getModules() {
    val moduleEntities = viewModel.getModules()
    assertNotNull(moduleEntities)
    assertEquals(7, moduleEntities.size.toLong())
    }

    @Test
    fun getSelectedModule() {
    val moduleEntity = viewModel.getSelectedModule()
    assertNotNull(moduleEntity)
    val contentEntity = moduleEntity.contentEntity
    assertNotNull(contentEntity)
    val content = contentEntity?.content
    assertNotNull(content)
    assertEquals(content, dummyModules[0].contentEntity?.content)
    }
    }
    Java
    public class CourseReaderViewModelTest {

    private CourseReaderViewModel viewModel;

    private CourseEntity dummyCourse = DataDummy.generateDummyCourses().get(0);
    private String courseId = dummyCourse.getCourseId();
    private ArrayList<ModuleEntity> dummyModules = DataDummy.generateDummyModules(courseId);
    private String moduleId = dummyModules.get(0).getModuleId();

    @Before
    public void setUp() {
    viewModel = new CourseReaderViewModel();
    viewModel.setSelectedCourse(courseId);
    viewModel.setSelectedModule(moduleId);

    ModuleEntity dummyModule = dummyModules.get(0);
    dummyModule.contentEntity = new ContentEntity("<h3 class=\\\"fr-text-bordered\\\">" + dummyModule.getTitle() + "</h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>");
    }

    @Test
    public void getModules() {
    ArrayList<ModuleEntity> moduleEntities = viewModel.getModules();
    assertNotNull(moduleEntities);
    assertEquals(7, moduleEntities.size());
    }

    @Test
    public void getSelectedModule() {
    ModuleEntity moduleEntity = viewModel.getSelectedModule();
    assertNotNull(moduleEntity);
    ContentEntity contentEntity = moduleEntity.contentEntity;
    assertNotNull(contentEntity);
    String content = contentEntity.getContent();
    assertNotNull(content);
    assertEquals(content, dummyModules.get(0).contentEntity.getContent());
    }
    }
    Jalankan pengujian pada kelas tersebut, maka hasil pengujiannya jadi seperti ini:
    W2eCsJkDgtQmelUwGo4Z5ozmNpFZhgt4a3Pw6hXWLCaBRiG38yoMnL-YDJTuMHOMhXqyWBXrpMjYStszUqYHofBbJmvRaiynTDJqgUbZg68f5lLKg8DCbpE_s7jg3RXANxDtzaX0
    Selamat, Anda juga berhasil menguji CourseReaderViewModel dengan cara membandingkan ukuran dari array viewModel.getModules() dan membandingkan data ModuleEntity hasil dari viewModel.getSelectedModule().
Mantap! Anda sudah melakukan pengujian setiap ViewModel yang ada pada proyek Academy. Namun, Anda juga perlu melakukan Instrumental Test untuk menguji apakah secara ui, kode Anda sudah berjalan sudah benar.

Codelab Instrumental Testing ViewModel

  1. Sebelum Anda melakukan Instrumental Testing, Anda perlu membuat skenario testing yang dilakukan:
    • Menampilkan data kursus academy
      • Memastikan rv_academy dalam keadaan tampil.
      • Gulir rv_academy ke posisi data terakhir.
    • Menampilkan data detail kursus academy
      • Memberi tindakan klik pada data pertama di rv_academy.
      • Memastikan TextView untuk title tampil sesuai dengan yang diharapkan.
      • Memastikan TextView untuk deadline tampil sesuai dengan yang diharapkan.
    • Menampilkan data modul
      • Memberi tindakan klik pada data pertama di rv_academy.
      • Memberi tindakan klik pada btn_start.
      • Memastikan rv_module dalam keadaan tampil.
    • Menampilkan data kursus academy
      • Memberi tindakan klik pada data pertama di rv_academy.
      • Memberi tindakan klik pada btn_start.
      • Memberi tindakan klik pada data pertama di rv_module
      • Memastikan web_view sudah tampil.
    • Menampilkan data bookmark
      • Klik TabLayout dengan teks Bookmark
      • Memastikan rv_module dalam keadaan tampil.
      • Gulir rv_module ke posisi data terakhir.
  2. Selanjutnya Anda perlu menambahkan library yang digunakan untuk pengujian. Bukalah build.gradle (project), tambahkan kode berikut:
    ext {
    //dependencies version
    appCompatVersion = '1.1.0'
    coreVersion = '1.1.0'
    constraintLayoutVersion = '1.1.3'
    junitVersion = '4.12'
    espressoVersion = '3.1.0'
    androidXTestVersion = '1.2.0'

    materialVersion = '1.0.0'
    recyclerViewVersion = '1.1.0'
    glideVersion = '4.10.0'

    archLifecycleVersion = '2.1.0'
    }
    Kemudian bukalah build.gradle (module:app), tambahkan kode berikut:
    androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
    androidTestImplementation "androidx.test:rules:$androidXTestVersion"

  3. Bukalah HomeActivity, kemudian klik ALT + Enter di bagian HomeActivity seperti ini:
    Kotlin
    20191219162518840eba9134f6227ef3911c261e8335d3.png
    Java
    20191219162429d3ff1bf0d8036a0d373441875f6d2f9d.png
    Kemudian pilih Create Test, maka akan muncul tampilan seperti ini:
    XkFdFVGKw1coL_G2AyeTsrDKvWEj7t7mEA-Z1kxkmuxicu8MKYIWJojaro0pzDn_UNwSdp_RPu8P4QmFbRWRzeZU83jJW9zIJcrWqOsv8IfGxzhawdH00EYLQu-2bRNK18VF88gr
    Biarkan nama default seperti tampilan di atas, kemudian tekan tombol OK maka akan muncul pilihan tujuan pembuatan kelas. Karena Anda akan melakukan Instrumental Testing, maka pilih folder androidTest.
    M-Xv8FztrMbBEZskoGTJHw0qdUKjYqA3luMxlyEXY8jyVOeDO11WIc6nrvmNW1j3MGRG_Ob2ww-3WSbEI8H_W5qrIxtxsaINPc3RfPNWSBJzGLL3aX85dTYK1SefBUuSkQi0eze6
    Tekan tombol OK, secara otomatis akan ada sebuah kelas baru dengan nama HomeActivityTest.
    201912191626364cf4e9b622b6703e8a50442f1fa4c063.pngCatatan:Hapuslah ExampleInstrumentedTest, karena kita tidak akan memakai kelas tersebut.
  4. Bukalah kelas HomeAcademyTest, buatlah pengujian sesuai dengan skenario seperti berikut:
    Kotlin
    class HomeActivityTest {

    private val dummyCourse = DataDummy.generateDummyCourses()

    @get:Rule
    var activityRule = ActivityTestRule(HomeActivity::class.java)

    @Test
    fun loadCourses() {
    onView(withId(R.id.rv_academy)).check(matches(isDisplayed()))
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(dummyCourse.size))
    }

    @Test
    fun loadDetailCourse() {
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))
    onView(withId(R.id.text_title)).check(matches(isDisplayed()))
    onView(withId(R.id.text_title)).check(matches(withText(dummyCourse[0].title)))
    onView(withId(R.id.text_date)).check(matches(isDisplayed()))
    onView(withId(R.id.text_date)).check(matches(withText("Deadline ${dummyCourse[0].deadline}")))
    }

    @Test
    fun loadModule() {
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))
    onView(withId(R.id.btn_start)).perform(click())
    onView(withId(R.id.rv_module)).check(matches(isDisplayed()))
    }

    @Test
    fun loadDetailModule() {
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))
    onView(withId(R.id.btn_start)).perform(click())
    onView(withId(R.id.rv_module)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))
    onView(withId(R.id.web_view)).check(matches(isDisplayed()))
    }

    @Test
    fun loadBookmarks() {
    onView(withText("Bookmark")).perform(click())
    onView(withId(R.id.rv_bookmark)).check(matches(isDisplayed()))
    onView(withId(R.id.rv_bookmark)).perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(dummyCourse.size))
    }
    }
    Java
    public class HomeActivityTest {

    private ArrayList<CourseEntity> dummyCourse = DataDummy.generateDummyCourses();

    @Rule
    public ActivityTestRule activityRule = new ActivityTestRule<>(HomeActivity.class);

    @Test
    public void loadCourses() {
    onView(withId(R.id.rv_academy)).check(matches(isDisplayed()));
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.scrollToPosition(dummyCourse.size()));
    }

    @Test
    public void loadDetailCourse() {
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
    onView(withId(R.id.text_title)).check(matches(isDisplayed()));
    onView(withId(R.id.text_title)).check(matches(withText(dummyCourse.get(0).getTitle())));
    onView(withId(R.id.text_date)).check(matches(isDisplayed()));
    onView(withId(R.id.text_date)).check(matches(withText(String.format("Deadline %s", dummyCourse.get(0).getDeadline()))));
    }

    @Test
    public void loadModule() {
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
    onView(withId(R.id.btn_start)).perform(click());
    onView(withId(R.id.rv_module)).check(matches(isDisplayed()));
    }

    @Test
    public void loadDetailModule() {
    onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
    onView(withId(R.id.btn_start)).perform(click());
    onView(withId(R.id.rv_module)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
    onView(withId(R.id.web_view)).check(matches(isDisplayed()));
    }

    @Test
    public void loadBookmarks() {
    onView(withText("Bookmark")).perform(click());
    onView(withId(R.id.rv_bookmark)).check(matches(isDisplayed()));
    onView(withId(R.id.rv_bookmark)).perform(RecyclerViewActions.scrollToPosition(dummyCourse.size()));
    }
    }
  5. Kemudian jalankan test dengan cara klik kanan pada class HomeActivityTest dan klik Run 'HomeActivityTest'.
    201912191631492bc45f09c5718f762d18924a415e6c7f.pngBisa juga dengan klik icon hijau seperti gambar ini:
    20191219163301cef43de77e20dbc99eccdefeace2c757.pngMaka device akan otomatis melakukan aksi sesuai dengan yang diskenariokan seperti ini:
    20191219163755ae46abdd98fe2054fc4fa0dce9a7bda9.gifDan kalau dilihat hasil testnya seperti ini:20191219163640a7308d0a2ccd712128964976570b1950.pngSelamat! Anda berhasil menguji AcademyTest.

Bedah Kode

UnitTest

Materi unit test secara umum sama dengan yang ada di modul latihan. Anda bisa lihat kembali untuk fungsi test yang digunakan seperti assert, verify, when() dll.

Tiga Komponen Utama dari Espresso:

Anda menggunakan Espresso dalam melakukan Instrumental Testing, berikut adalah 3 komponen utamanya:
  1. ViewMatchers (onView(ViewMatcher)): untuk menemukan elemen atau komponen antarmuka yang diuji.
  2. ViewActions (perform(ViewAction)): untuk memberikan event untuk melakukan sebuah aksi pada komponen antarmuka yang diuji.
  3. ViewAssertions: sebuah kondisi atau state dari komponen yang diuji.
Perhatikan kode berikut:
Kotlin
@get:Rule
var activityRule = ActivityTestRule(HomeActivity::class.java)
Java
@Rule
public ActivityTestRule activityRule = new ActivityTestRule<>(HomeActivity.class);
Annotation Rule digunakan untuk memanggil activity mana yang akan di-launch atau diluncurkan.

Selain itu perhartikan kode berikut:
Kotlin
onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(dummyCourse.size))
...
onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))
Java
onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.scrollToPosition(dummyCourse.size()));
...
onView(withId(R.id.rv_academy)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Jika diperhartikan, di sini terdapat kode RecyclerViewActions yang digunakan untuk pengujian pada RecyclerView seperti scroll ke posisi tertentu dan klik pada posisi tertentu. Kode ini merupakan hasil dari penambahan library
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"

Menarik bukan? Jadi ketika Anda membuat sebuah fitur, Anda perlu menyiapkan skenario pengujian untuk menguji fitur tersebut. Karena jika tidak, Aplikasi yang Anda buat bisa saja menyimpan eror atau bug yang tidak Anda ketahui.
Anda bisa unduh proyek Academy tentang Pengujian ViewModel di sini:
Codelabs selanjutnya akan membahas tentang Repository yang ada pada proyek Academy. Tetap semangat!