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:
- Kotlin programlama dili
- Temel Android Jetpack kitaplıkları:
ViewModel
veLiveData
- Uygulama mimarisi, Uygulama mimarisi rehberi ve Android Fundamentals codelab'deki kalıbı takip eder
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
veViewModel
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:
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:
- Viewlablab manzaralı oda
- Android Kotlin Fundamentals eğitim codelab'leri
- Gelişmiş Android eğitim codelab'leri
- Android Ayçiçeği Örneği
- Kotlin Udacity eğitim kursuyla Android Uygulamaları Geliştirme
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: | |
| Görev ekranı ekleme veya düzenleme: Görev eklemek veya düzenlemek için kullanıcı arayüzü katman kodu. |
| Veri katmanı: Görevlerin veri katmanıyla ilgilidir. Veritabanı, ağı ve depo kodunu içerir. |
| İstatistik ekranı: İstatistik ekranı için kullanıcı arayüzü katman kodu. |
| Görev ayrıntıları ekranı: Tek bir görev için kullanıcı arayüzü katman kodu. |
| Görevler ekranı: Tüm görevlerin listesi için kullanıcı arayüzü katman kodu. |
| 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.
- 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
- ExampleUnitTest.kt dosyasını bulana kadar
test
klasörünü açın. - 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:
- 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.
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
}
}
- Testi çalıştırın.
- Test sonuçlarında, testin yanında X işaretini görürsünüz.
- Ş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.
androidTest
kaynak grubunu açın.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
main
kaynak kümesindekitodoapp.statistics
içindeStatisticsUtils.kt
'i açın.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.
getActiveAndCompletedStats
öğesini sağ tıklayın ve Oluştur > Test'i seçin.
Test Oluştur iletişim kutusu açılır:
- Sınıf adı:'nı
StatisticsUtilsTest
olarak değiştirin (StatisticsUtilsKtTest
yerine KT'yi kullanmamak daha iyidir). - 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). - 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.
- Yerel testler yazacağınız için
test
dizinini (androidTest
değil) seçin. - Tamam'ı tıklayın.
test/statistics/
içindeStatisticsUtilsTest
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.
StatisticsUtilsTest
'yi açın.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
}
}
- Bir test olduğunu belirtmek için işlev adının üst kısmına
@Test
ek açıklamasını ekleyin. - Görev listesi oluşturun.
// Create an active task
val tasks = listOf<Task>(
Task("title", "desc", isCompleted = false)
)
- Bu görevler için
getActiveAndCompletedStats
numaralı telefonu arayın.
// Call your function
val result = getActiveAndCompletedStats(tasks)
- 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)
}
}
- 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.
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ızcaandroidTest
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
getActiveAndCompletedStats_noCompleted_returnsHundredZero()
testiniassertEquals
yerine Hamcrest'sassertThat
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))
}
}
- Ç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:
- Tamamlanmış bir görev varsa ve etkin görev yoksa
activeTasks
yüzdesi0f
ve tamamlanmış görev yüzdesi100f
olmalıdır . - Tamamlanan iki görev ve üç etkin görev varsa tamamlanan yüzde
40f
ve etkin yüzde60f
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.
- Belirtilen, Ne Zaman, Sonra yapısını kullanarak ve kuralı takip eden bir adla testi yazın.
- Testin başarısız olduğunu onaylayın.
- Testi geçmek için minimum kodu yazın.
- 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.
- Boş bir liste (
emptyList()
) varsa her iki yüzde değeri de 0f olmalıdır. - Görevler yüklenirken bir hata oluştuysa liste
null
ve her iki yüzde de 0f olacaktır. - 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.
tasks
null
veya boşsa0f
değerini döndürerekgetActiveAndCompletedStats
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
)
}
}
- 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 Event
nı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.
- Test etmek istediğiniz sınıfı
tasks
paketinde,TasksViewModel.
açın - Kodda, sınıf adını sağ tıklayın
TasksViewModel
-> Generate -> Test.
- Test Oluştur ekranında, kabul etmek için Tamam'ı tıklayın (varsayılan ayarları değiştirmenize gerek yoktur).
- 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.
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:
- AndroidX Test çekirdekini ve harici bağımlılıklarını ekleyin
- Robolectric Test kitaplığı bağımlılığını ekleyin
- AndroidJunit4 test çalıştırıcısıyla sınıfa ek açıklama ekleyin
- 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
- 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
- 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.getApplicationContex
t
yöntemi de dahildir.
- AndroidX test kitaplığından
ApplicationProvider.getApplicationContext()
kullanarak birTasksViewModel
oluşturun.
TasksViewModelTest.kt
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
tasksViewModel
numaralı telefondanaddNewTask
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
}
- Ç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.
- 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:
InstantTaskExecutorRule
hareketini kullanınLiveData
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!
- 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"
TasksViewModelTest.kt
uygulamasını açInstantTaskExecutorRule
öğesiniTasksViewModelTest
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.
test
kaynak grubunuzdaLiveDataTestUtil.kt
adlı yeni bir Kotlin dosyası oluşturun.
- 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.
getOrAwaitValue
kullanaraknewTaskEvent
içinLiveData
değerini alın.
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
- 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()))
}
}
- 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.
- Referans için
addNewTask_setsNewTaskEvent()
komutunu kullanaraksetFilterAllTasks_tasksAddViewVisible()
alanınaTasksViewModelTest
adlı bir test yazın. Bu testte filtreleme moduALL_TASKS
olarak ayarlanır vetasksAddViewVisible
LiveData'nıntrue
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
- 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ı AndroidXApplicationProvider.getApplicationContext()
ifadesini kullanarak oluşturursunuz.ALL_TASKS
filtre türü sıralamasında iletereksetFiltering
yöntemini çağırırsınız.getOrAwaitNextValue
yöntemini kullanaraktasksAddViewVisible
öğ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.
tasksViewModel|
adlı birlateinit
örnek değişkeni oluşturun.setupViewModel
adlı bir yöntem oluşturun.@Before
ile not ekleyin.- 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())
}
- 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.
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ı:
- Uygulama mimarisi rehberi
- JUnit4
- Hamcrest
- Robolectric Test kitaplığı
- AndroidX Test Kitaplığı
- AndroidX Mimari Bileşenleri Temel Test Kitaplığı
- kaynak grupları
- Komut satırından test etme
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.