Testle İlgili Temel Bilgiler

Bu codelab, Kotlin'deki Gelişmiş Android kursuna dahildir. Codelab'ler sırasında sırayla çalıştığınızda bu kurstan en yüksek değeri elde edersiniz ancak zorunlu değildir. Tüm kurs codelab'leri Kotlin Codelab'de Gelişmiş Android açılış sayfasında listelenmiştir.

Giriş

İlk uygulamanızın ilk özelliğini uyguladığınızda, muhtemelen beklendiği gibi çalıştığını doğrulamak için kodu çalıştırmıştınız. Test uygulamış olsanız da manuel test yaptınız. Özellik ekleyip güncellemeye devam ettikçe, büyük olasılıkla kodunuzu çalıştırmaya ve kodunuzu doğrulamaya da devam etmiş olursunuz. Ancak bunu manuel olarak yapmak her zaman yorucu, hata yapmaya açıktır ve ölçeklendirilmez.

Bilgisayarlar, ölçeklendirme ve otomasyon için mükemmeldir. Bu nedenle, büyük veya küçük şirketlerdeki geliştiriciler, yazılım tarafından çalıştırılan ve kodun çalıştığını doğrulamak için uygulamayı manuel olarak çalıştırmanızı gerektirmeyen otomatik testler yazar.

Bu codelab serisinde öğreneceğiniz bir dizi testin (test paketi olarak bilinir) gerçek dünyaya ait bir uygulama için nasıl oluşturulacağını öğreneceksiniz.

İlk codelab'de Android'de testlerin temellerini öğreneceksiniz. İlk testlerinizi yazacak ve LiveData ve ViewModel'ları nasıl test edeceğinizi öğreneceksiniz.

Bilmeniz gerekenler

Aşağıdaki konular hakkında bilgi sahibi olmalısınız:

Neler öğreneceksiniz?

Aşağıdaki konular hakkında bilgi edineceksiniz:

  • Android'de birim testleri yazma ve çalıştırma
  • Test Odaklı Geliştirme nasıl kullanılır?
  • Enstrümantal testleri ve yerel testleri seçme

Aşağıdaki kitaplıklar ve kod kavramları hakkında bilgi edineceksiniz:

Yapacaklarınız

  • Android'de hem yerel hem de araçlı testleri kurun, çalıştırın ve yorumlayın.
  • JUnit4 ve Hamcrest kullanarak Android'de birim testleri yazın.
  • Basit LiveData ve ViewModel testleri yazın.

Bu codelab serisinde TO-DO Notes uygulamasıyla çalışacaksınız. Uygulama, tamamlamak için görevleri not etmenize ve bir listede göstermenize olanak sağlar. Ardından, tamamlandı olarak işaretleyebilir, filtreleyebilir veya silebilirsiniz.

Bu uygulama Kotlin'de yazılmış, birkaç ekrana sahiptir ve Jetpack bileşenlerini kullanır ve Uygulama mimarisi rehberinden mimariyi takip eder. Bu uygulamanın nasıl test edileceğini öğrenerek aynı kitaplık ve mimariyi kullanan uygulamaları test edebileceksiniz.

Başlamak için kodu indirin:

Zip'i İndir

Alternatif olarak, kod için Github veri deposunu klonlayabilirsiniz:

$ git clone https://github.com/googlecodelabs/android-testing.git
$ cd android-testing
$ git checkout starter_code

Bu görevde uygulamayı çalıştırıp kod tabanını keşfedeceksiniz.

1. Adım: Örnek uygulamayı çalıştırın

Yapılacaklar uygulamasını indirdikten sonra Android Studio'da açın ve çalıştırın. İçerik derlenmelidir. Aşağıdakileri yaparak uygulamayı keşfedin:

  • Artı kayan işlem düğmesini kullanarak yeni bir görev oluşturun. Önce bir başlık girin, ardından görev hakkında ek bilgiler girin. Kodu yeşil onay FAB'ı ile kaydedin.
  • Görevler listesinde, yeni tamamladığınız görevin başlığını tıklayın ve açıklamanın geri kalanını görmek için söz konusu görevin ayrıntı ekranına bakın.
  • Görevin listede veya ayrıntı ekranında durumunu Tamamlandı olarak ayarlamak için ilgili onay kutusunu işaretleyin.
  • Görevler ekranına dönün, filtre menüsünü açın ve görevleri Etkin ve Tamamlandı durumuna göre filtreleyin.
  • Gezinme çekmecesini açın ve İstatistikler'i tıklayın.
  • Genel bakış ekranına geri dönün ve gezinme çekmecesi menüsünden Tamamlandı durumuna sahip tüm görevleri silmek için Tamamlananları temizle'yi seçin

2. Adım: Örnek uygulama kodunu keşfedin

Yapılacaklar listesi, popüler Mimari Şemalar testine ve mimari örneğine dayalıdır (örneğin, reaktif mimari sürümü kullanılır). Uygulama, Uygulama mimarisi kılavuzundaki mimariyi kullanır. Parçalı Görünüm Modelleri, depo ve Oda kullanır. Aşağıdaki örneklerden herhangi birini biliyorsanız bu uygulamanın benzer bir mimarisi vardır:

Uygulamanın genel mimarisini anlamanız, herhangi bir katmandaki mantığı derinlemesine anlamanızdan daha önemlidir.

Göreceğiniz paketlerin özeti aşağıda verilmiştir:

Paket: com.example.android.architecture.blueprints.todoapp

.addedittask

Görev ekranı ekleme veya düzenleme: Görev eklemek veya düzenlemek için kullanıcı arayüzü katman kodu.

.data

Veri katmanı: Görevlerin veri katmanıyla ilgilidir. Veritabanı, ağı ve depo kodunu içerir.

.statistics

İstatistik ekranı: İstatistik ekranı için kullanıcı arayüzü katman kodu.

.taskdetail

Görev ayrıntıları ekranı: Tek bir görev için kullanıcı arayüzü katman kodu.

.tasks

Görevler ekranı: Tüm görevlerin listesi için kullanıcı arayüzü katman kodu.

.util

Yardımcı dersler: Uygulamanın çeşitli bölümlerinde kullanılan paylaşılan sınıflar (ör. birden fazla ekranda kullanılan kaydırma yenileme düzeni için).

Veri katmanı (.data)

Bu uygulama, yerel pakette, veritabanı (simüle edilmiş ağ katmanı) ve uzaktan paket halinde bir veritabanı katmanı içerir. Kolaylık sağlaması açısından bu projede ağ katmanı, gerçek ağ istekleri göndermek yerine gecikmeli olarak yalnızca bir HashMap ile simüle edilir.

DefaultTasksRepository, ağ iletişimi katmanı ile veritabanı katmanı arasında koordinasyon sağlar veya arabuluculuk yapar ve verileri kullanıcı arayüzü katmanına iletir.

Kullanıcı arayüzü katmanı ( .addedittask, .statistics, .taskdetail, .tasks)

Kullanıcı arayüzü katman paketlerinin her biri, parça ve görünüm modelinin yanı sıra kullanıcı arayüzü için gerekli olan diğer sınıfları (görev listesi için bağdaştırıcı gibi) içerir. TaskActivity, tüm parçaları içeren etkinliktir.

Gezinme

Uygulamada gezinme, Gezinme bileşeni tarafından kontrol edilir. nav_graph.xml dosyasında tanımlanır. Gezinme modelleri, Event sınıfı kullanılarak görünüm modellerinde tetiklenir. Görünüm modelleri, hangi bağımsız değişkenlerin iletileceğini de belirler. Parçalar Event'ları gözlemler ve ekranlar arasında gerçek gezinmeyi gerçekleştirirler.

Bu görevde ilk testlerinizi çalıştıracaksınız.

  1. Android Studio'da Proje bölmesini açın ve şu üç klasörü bulun:
  • com.example.android.architecture.blueprints.todoapp
  • com.example.android.architecture.blueprints.todoapp (androidTest)
  • com.example.android.architecture.blueprints.todoapp (test)

Bu klasörler kaynak kümeleri olarak bilinir. Kaynak kümeleri, uygulamanızın kaynak kodunu içeren klasörlerdir. Yeşil renkli kaynak grupları (androidTest ve test) testlerinizi içerir. Yeni bir Android projesi oluşturduğunuzda, varsayılan olarak aşağıdaki üç kaynak grubunu alırsınız. Bunlar:

  • main: Uygulama kodunuzu içerir. Bu kod, oluşturabileceğiniz uygulamanın tüm farklı sürümleri arasında paylaşılır (derleme varyantları olarak bilinir)
  • androidTest: Enstrümantal test olarak bilinen testleri içerir.
  • test: Yerel testler olarak bilinen testleri içerir.

Yerel testler ile araçlı testler arasındaki fark, çalıştırılma şekilleridir.

Yerel testler (test kaynak kümesi)

Bu testler geliştirme makinenizin JVM'sinde yerel olarak çalıştırılır ve emülatör veya fiziksel cihaz gerektirmez. Bu nedenle, bu reklamlar hızlı bir şekilde çalışır ancak doğrulukları daha düşüktür. Bu da, gerçek dünyada daha az davrandıkları anlamına gelir.

Android Studio'da yerel testler yeşil ve kırmızı üçgen simgesiyle temsil edilir.

Araçlı testler (androidTest kaynak grubu)

Bu testler gerçek veya emüle Android cihazlarda çalışır, dolayısıyla gerçek dünyada neler olacağını ama çok daha yavaş olduğunu gösterir.

Android Studio enstrümantasyon testleri, yeşil ve kırmızı üçgen simgesi olan bir Android ile temsil edilir.

1. Adım: Yerel test çalıştırın

  1. ExampleUnitTest.kt dosyasını bulana kadar test klasörünü açın.
  2. Sağ tıklayın ve SampleUnitTest'i Çalıştır'ı seçin.

Ekranın alt kısmındaki Çalıştır penceresinde aşağıdaki çıkışı görürsünüz:

  1. Yeşil onay işaretlerine dikkat edin ve test sonuçlarını genişleterek addition_isCorrect adlı bir testin geçtiğini doğrulayın. Eklemenin beklendiği gibi çalıştığını bilmekte fayda vardır.

2. Adım: Testin başarısız olmasını sağlayın

Aşağıda az önce çalıştırdığınız testi bulabilirsiniz.

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)
   }
}

Testlerin,

  • test kaynağı gruplarındaki bir sınıftır.
  • @Test ek açıklamasıyla başlayan işlevler içerir (her işlev tek bir testtir).
  • Kullanıcı onayı içeren ifadeler içerir.

Android, test için JUnit test kitaplığını kullanır (bu codelab JUnit4'te). Hem onaylamalar hem de @Test ek açıklaması JUnit'ten gelir.

Kırpma testinin temelini oluşturur. Kodunuzun veya uygulamanızın beklendiği gibi davrandığını kontrol eden bir kod ifadesidir. Bu durumda, assertEquals(4, 2 + 2) değeri 4'ün 2 + 2'ye eşit olup olmadığını kontrol eder.

Başarısız bir testin nasıl görüneceğini görmek için kolayca görebileceğiniz bir onaylama ekleyin. 3'ün 1+1'e eşit olup olmadığını kontrol eder.

  1. assertEquals(3, 1 + 1), addition_isCorrect testine eklenir.

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
   }
}
  1. Testi çalıştırın.
  1. Test sonuçlarında, testin yanında X işaretini görürsünüz.

  1. Şunları da unutmayın:
  • Tek bir başarısız onaylama, testin tamamının başarısız olmasını sağlar.
  • Beklenen değer (3) ile gerçekte hesaplanan değerin (2) karşılaştırılması.
  • Başarısız olan (ExampleUnitTest.kt:16) onay satırına yönlendirilirsiniz.

3. Adım: Enstrümantasyon testi yapın

Araçlı testler androidTest kaynak kümesindedir.

  1. androidTest kaynak grubunu açın.
  2. ExampleInstrumentedTest adlı testi çalıştırın.

ÖrnekEnstrümantasyon Testi

@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)
    }
}

Yerel testten farklı olarak bu test bir cihazda (emüle edilmiş Pixel 2 telefonun altındaki örnekte) çalıştırılır:

Cihazınız bağlıysa veya emülatör çalışıyorsa testin emülatörde çalıştığını görmeniz gerekir.

Bu görevde uygulamanız için etkin ve eksiksiz görev istatistiklerinin yüzdesini hesaplayan getActiveAndCompleteStats için testler yazın. Bu sayıları uygulamanın istatistik ekranında görebilirsiniz.

1. Adım: Bir test sınıfı oluşturun

  1. main kaynak kümesindeki todoapp.statistics içinde StatisticsUtils.kt'i açın.
  2. getActiveAndCompletedStats işlevini bulun.

İstatistiklerUtils.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)

getActiveAndCompletedStats işlevi, görevlerin listesini kabul eder ve bir StatsResult döndürür. StatsResult iki sayı içeren bir veri sınıfıdır; tamamlanan görevlerin yüzdesi ve etkin olan yüzdesidir.

Android Studio, bu işlev için testleri uygulamanıza yardımcı olmak amacıyla test stub'ları oluşturmak için araçlar sağlar.

  1. getActiveAndCompletedStats öğesini sağ tıklayın ve Oluştur > Test'i seçin.

Test Oluştur iletişim kutusu açılır:

  1. Sınıf adı:'nı StatisticsUtilsTest olarak değiştirin (StatisticsUtilsKtTest yerine KT'yi kullanmamak daha iyidir).
  2. Varsayılanların geri kalanını değiştirmeyin. JUnit 4, uygun test kitaplığıdır. Hedef paket doğru (StatisticsUtils sınıfın konumunu yansıtıyor) ve onay kutularının herhangi birini işaretlemeniz gerekmez (bu işlem yalnızca ek kod oluşturur ancak testinizi sıfırdan yazarsınız).
  3. Tamam'a basın

Destination Directory'yi seçin iletişim kutusu açılır:

İşleviniz matematik hesaplamaları yaptığı ve Android'e özel herhangi bir kod içermeyeceği için yerel test gerçekleştireceksiniz. Dolayısıyla gerçek zamanlı veya emüle edilmiş bir cihazda çalıştırmanız gerekmez.

  1. Yerel testler yazacağınız için test dizinini (androidTest değil) seçin.
  2. Tamam'ı tıklayın.
  3. test/statistics/ içinde StatisticsUtilsTest sınıfının oluşturulduğuna dikkat edin.

2. Adım: İlk test fonksiyonunuzu yazın

Aşağıdakileri kontrol eden bir test yazacaksınız:

  • tamamlanmış görev ve etkin bir görev yoksa
  • Aktif test yüzdesi %100 ise
  • Tamamlanan görevlerin yüzdesi %0'dır.
  1. StatisticsUtilsTest'yi açın.
  2. getActiveAndCompletedStats_noCompleted_returnsHundredZero adlı bir işlev oluşturun.

İstatistiklerUtilsTest.kt

class StatisticsUtilsTest {

    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
        // Create an active task

        // Call your function

        // Check the result
    }
}
  1. Bir test olduğunu belirtmek için işlev adının üst kısmına @Test ek açıklamasını ekleyin.
  2. Görev listesi oluşturun.
// Create an active task 
val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
  1. Bu görevler için getActiveAndCompletedStats numaralı telefonu arayın.
// Call your function
val result = getActiveAndCompletedStats(tasks)
  1. Onayları kullanarak result beklediğinizden emin olun.
// Check the result
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)

Kodun tamamı aşağıda verilmiştir.

İstatistiklerUtilsTest.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)
    }
}
  1. Testi çalıştırın (StatisticsUtilsTest öğesini sağ tıklayın ve Çalıştır'ı seçin).

Şunu iletmelidir:

3. Adım: Hamcrest bağımlılığını ekleyin

Testleriniz, kodunuzun işlevine dair bir belge görevi gördüğü için, kullanıcılar tarafından okunabilir olduğunda da faydalıdır. Şu iki iddiayı karşılaştırın:

assertEquals(result.completedTasksPercent, 0f)

// versus

assertThat(result.completedTasksPercent, `is`(0f))

İkinci iddia, insan cümlesine çok daha fazla benziyor. Hamcrest adlı bir onay çerçevesi kullanılarak yazılmıştır. Okunabilir iddialar yazmak için bir başka iyi araç da Doğruluk kitaplığı'dır. Onayları yazmak için bu codelab'de Hamcrest'i kullanacaksınız.

  1. build.grade (Module: app) öğesini açın ve aşağıdaki bağımlıyı ekleyin.

uygulama/derleme.gradle

dependencies {
    // Other dependencies
    testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
}

Bağımlılık eklerken genellikle implementation kullanıyorsunuz, ancak burada testImplementation kullanıyorsunuz. Uygulamanızı dünyayla paylaşmaya hazır olduğunuzda, en iyisi APK'nızın boyutunu test kodu ya da bağımlılığı olan herhangi bir içerikle engellememektir. gradle yapılandırmalarını kullanarak bir kitaplığın ana koda mı yoksa test koduna mi dahil edileceğini belirtebilirsiniz. En yaygın yapılandırmalar şunlardır:

  • implementation: Bağımlılık, test kaynağı grupları da dahil olmak üzere tüm kaynak gruplarında kullanılabilir.
  • testImplementation: Bağımlılık yalnızca test kaynağı grubunda kullanılabilir.
  • androidTestImplementation: Bağımlılık yalnızca androidTest kaynak kümesinde kullanılabilir.

Hangi yapılandırmanın kullanıldığı, bağımlılığın kullanılabileceği yerleri tanımlar. Yazacaklarınız:

testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"

Yani Hamcrest yalnızca test kaynağı grubunda kullanılabilir. Ayrıca, Hamcrest'in son uygulamanıza dahil edilmemesini de sağlar.

4. Adım: Onaylar yazmak için Hamcrest'i kullanın

  1. getActiveAndCompletedStats_noCompleted_returnsHundredZero() testini assertEquals yerine Hamcrest's assertThat kullanacak şekilde güncelleyin.
// REPLACE
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)

// WITH
assertThat(result.activeTasksPercent, `is`(100f))
assertThat(result.completedTasksPercent, `is`(0f))

İstenirse içe aktarma işlemini import org.hamcrest.Matchers.`is` kullanabilirsiniz.

Son test, aşağıdaki koda benzer.

İstatistiklerUtilsTest.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))

    }
}
  1. Çalıştığından emin olmak için güncellenmiş testinizi çalıştırın.

Bu codelab'de, Hamcrest'le ilgili tüm ayrıntılar öğretilmeyecek. Bu nedenle, daha fazla bilgi edinmek istiyorsanız resmi eğiticiye göz atabilirsiniz.

Bu, alıştırma için isteğe bağlı bir görevdir.

Bu görevde JUnit ve Hamcrest kullanarak daha fazla test yazacaksınız. Ayrıca, Test Destekli Geliştirme program uygulamasından türetilen bir stratejiyi kullanarak testler yazarsınız. Test sürüşü Geliştirme veya TDD, öncelikle özellik kodunuzu yazmak yerine testlerinizi önce yazdığınızı belirten bir programlama okuludur. Ardından, testlerinizi geçmek amacıyla özellik kodunuzu yazarsınız.

1. Adım: Testleri yazma

Normal bir görev listeniz olduğunda testler yazın:

  1. Tamamlanmış bir görev varsa ve etkin görev yoksa activeTasks yüzdesi 0f ve tamamlanmış görev yüzdesi 100f olmalıdır .
  2. Tamamlanan iki görev ve üç etkin görev varsa tamamlanan yüzde 40f ve etkin yüzde 60f olmalıdır.

2. Adım: Hata için test yazın

Yazıldığı şekilde getActiveAndCompletedStats kodunda hata var. Liste boşsa veya boşsa ne olacağını doğru şekilde işlemez. Her iki durumda da her iki yüzde değeri de sıfır olmalıdır.

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()
   )
  
}

Kodu düzeltmek ve test yazmak için test odaklı geliştirmeyi kullanırsınız. Test Yönelimli Geliştirme aşağıdaki adımları uygular.

  1. Belirtilen, Ne Zaman, Sonra yapısını kullanarak ve kuralı takip eden bir adla testi yazın.
  2. Testin başarısız olduğunu onaylayın.
  3. Testi geçmek için minimum kodu yazın.
  4. Tüm testler için tekrarlayın!

Hatayı düzeltmek yerine önce testleri yazarak başlarsınız. Ardından, gelecekte bu hataların yanlışlıkla tekrar eklenmesini önlemek için testler gerçekleştirdiğinizi doğrulayabilirsiniz.

  1. Boş bir liste (emptyList()) varsa her iki yüzde değeri de 0f olmalıdır.
  2. Görevler yüklenirken bir hata oluştuysa liste null ve her iki yüzde de 0f olacaktır.
  3. Testlerinizi çalıştırın ve başarısız olduklarını onaylayın:

3. Adım: Hatayı düzeltin

Artık testlerinizi oluşturduğunuza göre hatayı düzeltebilirsiniz.

  1. tasks null veya boşsa 0f değerini döndürerek getActiveAndCompletedStats hatasını düzeltin:
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
        )
    }
}
  1. Testlerinizi tekrar çalıştırın ve tüm testlerin tamamlandığını onaylayın.

TDD'yi takip edip testleri önce yazarak, aşağıdakileri yapmanıza yardımcı oldunuz:

  • Yeni işlevler her zaman ilişkilendirilmiş testlere sahiptir; bu nedenle testleriniz, kodunuzun ne yaptığına dair bir doküman görevi görür.
  • Testleriniz doğru sonuçları kontrol eder ve gördüğünüz hatalara karşı koruma sağlar.

Çözüm: Daha fazla test yazma

Burada tüm testleri ve ilgili özellik kodunu bulabilirsiniz.

İstatistiklerUtilsTest.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))
    }
}

İstatistiklerUtils.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
        )
    }
}

Test yazma ve çalıştırmayla ilgili temel bilgileri edindiniz. Ardından, temel ViewModel ve LiveData testlerinin nasıl yazılacağını öğreneceksiniz.

Codelab'in geri kalanında, çoğu uygulamada yaygın olan iki Android sınıfı (ViewModel ve LiveData) için testlerin nasıl yazılacağını öğreneceksiniz.

İlk olarak TasksViewModel için testler oluşturursunuz.


Görünüm modelinde tüm mantıka sahip olan ve depo kodu kullanmayan testlere odaklanacaksınız. Kod deposu kodu, eşzamansız kod, veritabanları ve ağ çağrılarını içerir. Bu da test karmaşıklığı sağlar. Şu an için bundan kaçınacak ve depodaki hiçbir şeyi doğrudan test etmeyen ViewModel işlevleri için testler yazmaya odaklanacaksınız.



Yazacağınız test, addNewTask yöntemini aradığınızda yeni görev penceresini açmak için Eventnın tetiklenip tetiklenmediğini kontrol edecektir. Test edeceğiniz uygulama kodu burada verilmiştir.

TasksViewModel.kt

fun addNewTask() {
   _newTaskEvent.value = Event(Unit)
}

1. Adım: TasksViewModelTest sınıfı oluşturma

StatisticsUtilTest için yaptığınız adımları uygulayarak bu adımda TasksViewModelTest için bir test dosyası oluşturursunuz.

  1. Test etmek istediğiniz sınıfı tasks paketinde, TasksViewModel. açın
  2. Kodda, sınıf adını sağ tıklayın TasksViewModel -> Generate -> Test.

  1. Test Oluştur ekranında, kabul etmek için Tamam'ı tıklayın (varsayılan ayarları değiştirmenize gerek yoktur).
  2. Destination Directory (İletişim Dizinini Seç) iletişim kutusunda test dizinini seçin.

2. Adım: ViewModel Testinizi Yazmaya Başlayın

Bu adımda, addNewTask yöntemini çağırdığınızda yeni görev penceresini açmak için Event işleminin tetiklendiğini test etmek üzere bir görünüm modeli testi eklersiniz.

  1. addNewTask_setsNewTaskEvent adında yeni bir test oluşturun.

TasksViewModelTest.kt

class TasksViewModelTest {

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh TasksViewModel


        // When adding a new task


        // Then the new task event is triggered

    }
    
}

Peki ya uygulama?

Test etmek için TasksViewModel örneği oluşturduğunuzda oluşturucunun bir Uygulama İçeriği gerekir. Ancak bu testte etkinlikler, kullanıcı arayüzü ve parçalarla tam bir uygulama oluşturmuyorsunuz. Peki, uygulama bağlamını nasıl elde edebilirsiniz?

TasksViewModelTest.kt

// Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(???)

AndroidX Test kitaplıkları, testlere yönelik Uygulamalar ve Etkinlikler gibi bileşenlerin sürümlerini sağlayan dersler ve yöntemler içerir. Simüle edilmiş Android çerçeve derslerine(Uygulama Bağlamı gibi) ihtiyacınız olan bir yerel testiniz olduğunda, AndroidX Testi'ni doğru bir şekilde ayarlamak için aşağıdaki adımları uygulayın:

  1. AndroidX Test çekirdekini ve harici bağımlılıklarını ekleyin
  2. Robolectric Test kitaplığı bağımlılığını ekleyin
  3. AndroidJunit4 test çalıştırıcısıyla sınıfa ek açıklama ekleyin
  4. AndroidX Test kodu yazma

Bu adımları tamamlayıp birlikte ne yaptıklarını birlikte anlayacaksınız.

3. Adım: Gradle bağımlılıklarını ekleyin

  1. Temel AndroidX Test çekirdeği ve harici bağımlılıklarının yanı sıra Robolectric test bağımlılığını eklemek için bu bağımlılıkları uygulama modülünüzün build.gradle dosyasına kopyalayın.

uygulama/derleme.gradle

    // AndroidX Test - JVM testing
testImplementation "androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion"

    testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"

 testImplementation "org.robolectric:robolectric:$robolectricVersion"

4. Adım. JUnit Test Çalıştırıcısı ekleyin

  1. Test sınıfınızın üst kısmına @RunWith(AndroidJUnit4::class) ekleyin.

TasksViewModelTest.kt

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
    // Test code
}

5. Adım: AndroidX Testi'ni kullan

Bu noktada AndroidX Test kitaplığını kullanabilirsiniz. Buna, bir Uygulama Bağlamı alan ApplicationProvider.getApplicationContext yöntemi de dahildir.

  1. AndroidX test kitaplığından ApplicationProvider.getApplicationContext() kullanarak bir TasksViewModel oluşturun.

TasksViewModelTest.kt

// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
  1. tasksViewModel numaralı telefondan addNewTask ile iletişime geçin.

TasksViewModelTest.kt

tasksViewModel.addNewTask()

Bu noktada testiniz aşağıdaki koda benzemelidir.

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
    }
  1. Çalıştığından emin olmak için testinizi çalıştırın.

Kavram: AndroidX Testi nasıl çalışır?

AndroidX Testi nedir?

AndroidX Test, test için çalışan bir kitaplık koleksiyonudur. Testler için tasarlanmış Uygulamalar ve Etkinlikler gibi bileşenlerin sürümlerini sunan dersler ve yöntemler içerir. Örnek olarak, yazdığınız bu kod uygulama bağlamını öğrenmek için bir AndroidX Test işlevine örnek olarak verilebilir.

ApplicationProvider.getApplicationContext()

AndroidX Test API'lerinin avantajlarından biri, hem yerel testler hem de cihazlı testlerde çalışacak şekilde geliştirilmiş olmasıdır. Bu şu nedenlerle güzeldir:

  • Yerel test veya enstrümantal test ile aynı testi çalıştırabilirsiniz.
  • Yerel ve araçlı testler için farklı test API'leri öğrenmeniz gerekmez.

Örneğin, kodunuzu AndroidX Test kitaplıklarını kullanarak yazdığınız için TasksViewModelTest sınıfınızı test klasöründen androidTest klasörüne taşıyabilirsiniz. Testler çalışmaya devam edecektir. getApplicationContext(), yerel veya göstergeli test olarak çalıştırılmasına bağlı olarak biraz farklı çalışır:

  • Enstrümantasyonlu testse, bir emülatörü başlattığında veya gerçek bir cihaza bağlandığında sağlanan gerçek Uygulama bağlamını alır.
  • Yerel test ise simüle edilmiş Android ortamı kullanır.

Robolectric nedir?

AndroidX Testi'nin yerel testler için kullandığı simülasyon simülasyonu Android ortamı Robolectric tarafından sağlanmaktadır. Robolectric, testler için simüle edilmiş bir Android ortamı oluşturan ve bir emülatörü başlatmak veya bir cihazda çalıştırmaktan daha hızlı çalışan bir kitaplıktır. Robolectric bağımlı olmadan şu hatayı alırsınız:

@RunWith(AndroidJUnit4::class) ne işe yarar?

Test çalıştırıcı , testleri çalıştıran bir JUnit bileşenidir. Test çalıştırıcısı olmadan testleriniz çalışmaz. JUnit tarafından sağlanan, otomatik olarak aldığınız bir varsayılan test çalıştırıcısı vardır. @RunWith, bu varsayılan test çalıştırıcısını değiştirir.

AndroidJUnit4 test çalıştırıcısı, AndroidX Testi'nin test enstrümantasyonuna veya yerel testlere bağlı olarak testinizi farklı bir şekilde çalıştırmasına olanak sağlar.

6. Adım: Robolectrik Uyarıları Düzelt

Kodu çalıştırdığınızda Robolectric'in kullanıldığını unutmayın.

AndroidX Testi ve AndroidJunit4 test çalıştırıcısı nedeniyle, bu doğrudan sizin tek bir Robolectric kodu satırı yazmadan yapılır.

İki uyarı görebilirsiniz.

  • No such manifest file: ./AndroidManifest.xml
  • "WARN: Android SDK 29 requires Java 9..."

Gradle dosyanızı güncelleyerek No such manifest file: ./AndroidManifest.xml uyarısını düzeltebilirsiniz.

  1. Doğru Android manifest'inin kullanılabilmesi için aşağıdaki satırı Gradle dosyanıza ekleyin. includeAndroidResources seçeneği, AndroidManifest dosyanız da dahil olmak üzere birim testlerinizdeki Android kaynaklarına erişmenizi sağlar.

uygulama/derleme.gradle

    // Always show the result of every unit test when running via command line, even if it passes.
    testOptions.unitTests {
        includeAndroidResources = true

        // ... 
    }

"WARN: Android SDK 29 requires Java 9..." uyarısı daha karmaşıktır. Android Q'da test çalıştırmak için Java 9 gerekir. Bu codelab'de, Android Studio'yu Java 9'u kullanacak şekilde yapılandırmaya çalışmak yerine hedefinizi 28 olarak derleyin.

Özet olarak:

  • Salt görüntüleme modeli testleri genellikle kodları Android'i gerektirmediği için test kaynak kümesinden geçebilir.
  • Uygulamalar ve Etkinlikler gibi bileşenlerin test sürümlerini almak için AndroidX testikitaplığı kullanabilirsiniz.
  • test kaynak grubunuzda simüle edilmiş Android kodu çalıştırmanız gerekirse Robolectric bağımlılık ve @RunWith(AndroidJUnit4::class) ek açıklamasını ekleyebilirsiniz.

Tebrikler, test çalıştırmak için hem AndroidX test kitaplığını hem de Robolectric'i kullanıyorsunuz. Testiniz bitmedi (henüz iddia beyanı yazmadınız, şimdi // TODO test LiveData diyor.) Ardından, LiveData ile iddia ifadeleri yazmayı öğreneceksiniz.

Bu görevde LiveData değeri için doğru şekilde nasıl hak talebinde bulunacağınızı öğreneceksiniz.

addNewTask_setsNewTaskEvent görüntüleme modeli testi olmadan burada kaldınız.

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
    }
    

LiveData uygulamasını test etmek için iki işlem yapmanız önerilir:

  1. InstantTaskExecutorRule hareketini kullanın
  2. LiveData gözlem

1. Adım: InstantTaskExecutorRule kullanın

InstantTaskExecutorRule bir JUnit Rule'dur. @get:Rule ek açıklamasıyla birlikte kullandığınızda InstantTaskExecutorRule sınıfındaki bazı kodların testlerden önce ve sonra çalıştırılmasına neden olur (tam kodu görmek için dosyayı Komut+B klavye kısayoluyla kullanabilirsiniz).

Bu kural, test sonuçlarının eşzamanlı ve tekrarlanabilir bir şekilde gerçekleşmesi için Mimari Bileşenler ile ilgili tüm arka plan işlerini aynı ileti dizisinde çalıştırır. LiveData testi içeren testler yazarken bu kuralı kullanın!

  1. Mimari Bileşenler temel test kitaplığı (bu kuralı içerir) için gradle bağımlılığını ekleyin.

uygulama/derleme.gradle

testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
  1. TasksViewModelTest.kt uygulamasını aç
  2. InstantTaskExecutorRule öğesini TasksViewModelTest sınıfının içine ekleyin.

TasksViewModelTest.kt

class TasksViewModelTest {
    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()
    
    // Other code...
}

2. Adım: LiveDataTestUtil.kt Sınıfını ekleyin

Sonraki adımınız, test ettiğiniz LiveData gözlemlendiğinden emin olmaktır.

LiveData hareketini kullandığınızda genellikle bir etkinlik veya parça (LifecycleOwner) gözlemlersiniz.

viewModel.resultLiveData.observe(fragment, Observer {
    // Observer code here
})

Bu gözlem önemlidir. LiveData için aktif gözlemcilere ihtiyacınız var

  • onChanged etkinliklerini tetikleyin.
  • herhangi bir Dönüşümü tetikler.

Görünüm modelinizin LiveData için beklenen LiveData davranışını elde etmek üzere bir LifecycleOwner ile birlikte LiveData parametresini gözlemlemeniz gerekir.

Bu bir sorun yaratıyor: TasksViewModel testinizde LiveData etkinliğinizi gözlemleyecek bir etkinliğiniz veya etkinliğiniz yok. Bu sorunu çözmek için observeForever yöntemini kullanabilirsiniz. Bu yöntem, LifecycleOwner eklenmesine gerek kalmadan LiveData kodunun sürekli olarak görülmesini sağlar. observeForever yaparken gözleminizi kaldırmayı veya gözlemleyici sızıntıyı riske atmayı unutmayın.

Bu, aşağıdaki koda benzeyecektir. İnceleme:

@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)
    }
}

Bu, test sırasında tek bir LiveData gözlemlemek için çok sayıda ortak metindir. Bu standart metinden kurtulmanın birkaç yolu vardır. Gözlemcileri eklemeyi kolaylaştırmak için LiveDataTestUtil adında bir uzantı işlevi oluşturacaksınız.

  1. test kaynak grubunuzda LiveDataTestUtil.kt adlı yeni bir Kotlin dosyası oluşturun.


  1. Aşağıdaki kodu kopyalayıp yapıştırın.

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
}

Bu, oldukça karmaşık bir yöntemdir. Gözlemciyi ekleyen, LiveData değerini alan ve ardından gözlemciyi (yukarıda gösterilen observeForever kodunun kısa, yeniden kullanılabilir bir sürümünü) temizleyen getOrAwaitValue adlı bir Kotlin uzantısı işlevi oluşturur. Bu sınıfın tam açıklaması için bu blog yayınını inceleyin.

3. Adım: Onay kutusunu yazmak için getOrAveValue kullanma

Bu adımda, getOrAwaitValue yöntemini kullanırsınız ve newTaskEvent öğesinin tetiklendiğini kontrol eden bir iddia ifadesi yazılır.

  1. getOrAwaitValue kullanarak newTaskEvent için LiveData değerini alın.
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
  1. Değerin null olmadığını doğrulayın.
assertThat(value.getContentIfNotHandled(), (not(nullValue())))

Testin tamamı aşağıdaki kodda görünmelidir.

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()))


    }

}
  1. Kodunuzu çalıştırın ve test kartını izleyin!

Artık test yazmayı öğrendiğinize göre kendiniz yazabilirsiniz. Bu adımda, edindiğiniz becerileri kullanarak başka bir TasksViewModel testi yazmayı deneyin.

1. Adım: Kendi ViewModel testinizi yazın

setFilterAllTasks_tasksAddViewVisible() yazacaksınız. Bu test, filtre türünüzü tüm görevleri gösterecek şekilde ayarladıysanız Görev ekle düğmesinin görünür olup olmadığını kontrol etmelidir.

  1. Referans için addNewTask_setsNewTaskEvent() komutunu kullanarak setFilterAllTasks_tasksAddViewVisible() alanına TasksViewModelTest adlı bir test yazın. Bu testte filtreleme modu ALL_TASKS olarak ayarlanır ve tasksAddViewVisible LiveData'nın true olduğunu belirtir.


Başlamak için aşağıdaki kodu kullanın.

TasksViewModelTest

    @Test
    fun setFilterAllTasks_tasksAddViewVisible() {

        // Given a fresh ViewModel

        // When the filter type is ALL_TASKS

        // Then the "Add task" action is visible
        
    }

Not:

  • Tüm görevler için TasksFilterType sıralama: ALL_TASKS.
  • Görev ekleme düğmesinin görünürlüğü LiveData tasksAddViewVisible. tarafından kontrol ediliyor
  1. Testinizi çalıştırın.

2. Adım: Testinizi çözümle karşılaştırın

Çözümünüzü aşağıdaki çözümle karşılaştırın.

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))
    }

Aşağıdakileri yapıp yapmadığınızı kontrol edin:

  • tasksViewModel öğenizi aynı AndroidX ApplicationProvider.getApplicationContext() ifadesini kullanarak oluşturursunuz.
  • ALL_TASKS filtre türü sıralamasında ileterek setFiltering yöntemini çağırırsınız.
  • getOrAwaitNextValue yöntemini kullanarak tasksAddViewVisible öğesinin doğru olup olmadığını kontrol edersiniz.

3. Adım: Bir @Önce kuralı ekleyin

Her iki testin de başlangıcında, TasksViewModel nasıl tanımlanır?

TasksViewModelTest

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

Birden fazla test için yinelenen kurulum kodunuz olduğunda, bir kurulum yöntemi oluşturmak ve yinelenen kodu kaldırmak için @Önce ek açıklamasını kullanabilirsiniz. Bu testlerin tümü TasksViewModel öğesini test edeceği ve bir görüntüleme modeli gerektirdiği için bu kodu bir @Before blokuna taşıyın.

  1. tasksViewModel| adlı bir lateinit örnek değişkeni oluşturun.
  2. setupViewModel adlı bir yöntem oluşturun.
  3. @Before ile not ekleyin.
  4. Görüntüleme modeli örnek kodunu setupViewModel adresine taşıyın.

TasksViewModelTest

    // Subject under test
    private lateinit var tasksViewModel: TasksViewModel

    @Before
    fun setupViewModel() {
        tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
    }
  1. Kodunuzu çalıştırın.

Uyarı

Aşağıdakileri yapmayın,

tasksViewModel

tanımıyla:

val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

Bu durum, tüm testler için aynı örneğin kullanılmasına neden olur. Her testin, testin altındaki konu (bu senaryoda ViewModel) için yeni bir örneği olması gerektiğinden, bunu önlemeniz gerekir.

TasksViewModelTest için son kod aşağıdaki koda benzemelidir.

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))
    }
    
}

Başladığınız kod ile nihai kod arasındaki farkı görmek için burayı tıklayın.

Tamamlanan codelab'in kodunu indirmek için aşağıdaki git komutunu kullanabilirsiniz:

$ git clone https://github.com/googlecodelabs/android-testing.git
$ cd android-testing
$ git checkout end_codelab_1


Alternatif olarak, veri havuzunu Zip dosyası olarak indirip sıkıştırılmış dosyayı Android Studio'da açabilirsiniz.

Zip'i İndir

Bu codelab'de şunlar ele alınmıştır:

  • Android Studio'dan test yapma.
  • Yerel (test) ve enstrümantasyon testleri (androidTest) arasındaki fark.
  • JUnit ve Hamcrest kullanarak yerel birim testleri yazma.
  • AndroidX Test Kitaplığı ile ViewModel testlerini ayarlama.

Udacity kursu:

Android geliştirici dokümanları:

Videolar:

Diğer:

Bu kurstaki diğer codelab'lerin bağlantıları için Kotlin codelab'lerdeki Gelişmiş Android açılış sayfasına bakın.