Bu codelab, Advanced Android in Kotlin kursunun bir parçasıdır. Bu kurstan en iyi şekilde yararlanmak için codelab'leri sırayla incelemeniz önerilir ancak bu zorunlu değildir. Kursla ilgili tüm codelab'ler Kotlin'de İleri Düzey Android codelab'leri açılış sayfasında listelenir.
Giriş
İlk uygulamanızın ilk özelliğini uyguladığınızda, beklendiği gibi çalıştığını doğrulamak için kodu çalıştırmış olabilirsiniz. Manuel test olsa da bir test gerçekleştirdiniz. Özellik eklemeye ve güncellemeye devam ettikçe kodunuzu çalıştırmaya ve çalıştığını doğrulamaya da devam etmiş olabilirsiniz. Ancak bunu her seferinde manuel olarak yapmak yorucudur, hatalara açıktır ve ölçeklenmez.
Bilgisayarlar ölçeklendirme ve otomasyon konusunda harikadır. Bu nedenle, büyük ve küçük şirketlerdeki geliştiriciler, yazılımlar 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, gerçek dünyadaki bir uygulama için test koleksiyonu (test paketi olarak da bilinir) oluşturmayı öğreneceksiniz.
Bu ilk codelab'de Android'de test etmenin temelleri ele alınmaktadır. İlk testlerinizi yazacak ve LiveData
ile ViewModel
'leri nasıl test edeceğinizi öğreneceksiniz.
Bilmeniz gerekenler
Aşağıdaki konular hakkında bilgi sahibi olmanız gerekir:
- Kotlin programlama dili
- Aşağıdaki temel Android Jetpack kitaplıkları:
ViewModel
veLiveData
- Uygulama mimarisi kılavuzu ve Android'in temelleri codelab'lerindeki kalıbı izleyen uygulama mimarisi
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?
- Araçlı testler ve yerel testler nasıl seçilir?
Aşağıdaki kitaplıklar ve kod kavramları hakkında bilgi edineceksiniz:
Yapacaklarınız
- Android'de hem yerel hem de enstrümanlı testleri ayarlama, çalıştırma ve yorumlama
- JUnit4 ve Hamcrest kullanarak Android'de birim testleri yazın.
- Basit
LiveData
veViewModel
testleri yazın.
Bu codelab serisinde, yapılacaklar notları uygulamasıyla çalışacaksınız. Bu uygulama, tamamlanacak görevleri yazmanıza ve bunları bir listede görüntülemenize olanak tanır. Ardından bunları tamamlandı veya tamamlanmadı olarak işaretleyebilir, filtreleyebilir ya da silebilirsiniz.
Bu uygulama Kotlin ile yazılmıştır, birden fazla ekranı vardır, Jetpack bileşenlerini kullanır ve Uygulama mimarisi kılavuzundaki mimariye uygundur. Bu uygulamayı nasıl test edeceğinizi öğrenerek aynı kitaplıkları ve mimariyi kullanan uygulamaları test edebilirsiniz.
Başlamak için kodu indirin:
Alternatif olarak, kod için GitHub deposunu klonlayabilirsiniz:
$ git clone https://github.com/googlecodelabs/android-testing.git $ cd android-testing $ git checkout starter_code
Bu görevde uygulamayı çalıştıracak ve kod tabanını keşfedeceksiniz.
1. adım: Örnek uygulamayı çalıştırın
TO-DO uygulamasını indirdikten sonra Android Studio'da açıp çalıştırın. Derlenmesi gerekir. Aşağıdaki adımları uygulayarak uygulamayı keşfedin:
- Kaydırma artı düğmesiyle yeni bir görev oluşturun. Önce başlık, ardından görevle ilgili ek bilgileri girin. Yeşil onay işaretiyle kaydedin.
- Görev listesinde, yeni tamamladığınız görevin başlığını tıklayın ve açıklamanın geri kalanını görmek için bu görevin ayrıntılar ekranına bakın.
- Listede veya ayrıntılar ekranında, görevin durumunu Tamamlandı olarak ayarlamak için görevin onay kutusunu işaretleyin.
- Görevler ekranına geri 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 dönün ve gezinme çekmecesi menüsünden Tamamlandı durumundaki tüm görevleri silmek için Tamamlananları temizle'yi seçin.
2. adım: Örnek uygulama kodunu inceleyin
Yapılacaklar uygulaması, popüler Architecture Blueprints test ve mimari örneğini (örneğin reactive architecture sürümünü kullanarak) temel alır. Uygulama, Uygulama mimarisi kılavuzundaki mimariye uygundur. Fragments, bir depo ve Room ile ViewModels kullanır. Aşağıdaki örneklerden herhangi birini biliyorsanız bu uygulamanın mimarisi benzerdir:
- Room with a View Codelab'i
- Android Kotlin Hakkında Temel Bilgiler eğitim codelab'leri
- İleri düzey Android eğitim codelab'leri
- Android Sunflower Sample
- Kotlin ile Android Uygulamaları Geliştirme Udacity eğitim kursu
Uygulamanın genel mimarisini anlamanız, herhangi bir katmandaki mantığı derinlemesine anlamanızdan daha önemlidir.
Bulacağınız paketlerin özeti:
Paket: | |
| Görev ekleme veya düzenleme ekranı: Görev ekleme veya düzenleme için kullanıcı arayüzü katmanı kodu. |
| Veri katmanı: Görevlerin veri katmanıyla ilgilidir. Veritabanı, ağ ve depo kodunu içerir. |
| İstatistikler ekranı: İstatistikler 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ı sınıflar: Uygulamanın çeşitli bölümlerinde kullanılan paylaşılan sınıflar (ör. birden fazla ekranda kullanılan yenilemek için kaydırma düzeni). |
Veri katmanı (.data)
Bu uygulama, remote paketinde simüle edilmiş bir ağ oluşturma katmanı ve local paketinde bir veritabanı katmanı içerir. Bu projede, basitlik için ağ katmanı gerçek ağ istekleri oluşturmak yerine yalnızca gecikmeli bir HashMap
ile simüle edilir.
DefaultTasksRepository
, ağ katmanı ile veritabanı katmanı arasında koordinasyon veya aracılık yapar ve verileri kullanıcı arayüzü katmanına döndürür.
Kullanıcı arayüzü katmanı ( .addedittask, .statistics, .taskdetail, .tasks)
Kullanıcı arayüzü katmanı paketlerinin her biri, bir fragment ve bir görünüm modelinin yanı sıra kullanıcı arayüzü için gereken diğer sınıfları (ör. görev listesi için bir bağdaştırıcı) içerir. TaskActivity
, tüm parçaları içeren etkinliktir.
Gezinme
Uygulamanın gezinme özelliği Navigation bileşeni tarafından kontrol edilir. Bu değer nav_graph.xml
dosyasında tanımlanır. Gezinme, 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
öğesini gözlemler ve ekranlar arasında gerçek gezinmeyi gerçekleştirir.
Bu görevde ilk testlerinizi çalıştıracaksınız.
- Android Studio'da Project (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 renkteki (androidTest ve test) kaynak kümeleri, testlerinizi içerir. Yeni bir Android projesi oluşturduğunuzda varsayılan olarak aşağıdaki üç kaynak kümesini alırsınız. Bunları şöyle sıralayabiliriz:
main
: Uygulama kodunuzu içerir. Bu kod, oluşturabileceğiniz uygulamanın tüm farklı sürümleri (derleme varyantları olarak bilinir) arasında paylaşılır.androidTest
: Araçlı testler olarak bilinen testleri içerir.test
: Yerel testler olarak bilinen testleri içerir.
Yerel testler ve enstrümanlı testler arasındaki fark, bunların çalıştırılma şeklindedir.
Yerel testler (test
kaynak grubu)
Bu testler, geliştirme makinenizin JVM'sinde yerel olarak çalıştırılır ve emülatör ya da fiziksel cihaz gerektirmez. Bu nedenle hızlı çalışırlar ancak doğrulukları daha düşüktür. Yani gerçek dünyada olduğu gibi davranmazlar.
Android Studio'da yerel testler yeşil ve kırmızı üçgen simgesiyle gösterilir.
Enstrümanlı testler (androidTest
kaynak grubu)
Bu testler gerçek veya emüle edilmiş Android cihazlarda çalıştırıldığından gerçek dünyada olacakları yansıtır ancak çok daha yavaştır.
Android Studio'da enstrümantasyonlu testler, yeşil ve kırmızı üçgen simgesi olan bir Android ile gösterilir.
1. adım: Yerel test çalıştırın
test
klasörünü ExampleUnitTest.kt dosyasını bulana kadar açın.- Dosyayı sağ tıklayın ve Run ExampleUnitTest'i (ExampleUnitTest'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
addition_isCorrect
adlı bir testin geçtiğini doğrulamak için test sonuçlarını genişletin. Ekleme işleminin beklendiği gibi çalıştığını öğrenmekten memnuniyet duyuyoruz.
2. adım: Testin başarısız olmasını sağlayın
Az önce çalıştırdığınız test aşağıda gösterilmektedir.
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 kaynak kümelerinden birinde sınıflandırılmış olmalıdır.
@Test
ek açıklamasıyla başlayan işlevler içerir (her işlev tek bir testtir).- genellikle onay ifadeleri içerir.
Android, test için JUnit test kitaplığını (bu codelab'de JUnit4) kullanır. Hem onaylamalar hem de @Test
ek açıklaması JUnit'ten gelir.
Onaylama, testinizin temelini oluşturur. Kodunuzun veya uygulamanızın beklendiği gibi çalıştığını kontrol eden bir kod ifadesidir. Bu durumda, 4'ün 2 + 2'ye eşit olup olmadığını kontrol eden assertEquals(4, 2 + 2)
ifadesi kullanılıyor.
Başarısız bir testin nasıl göründüğünü görmek için kolayca başarısız olması gerektiğini görebileceğiniz bir onaylama ekleyin. 3'ün 1+1'e eşit olup olmadığını kontrol eder.
assertEquals(3, 1 + 1)
öğesiniaddition_isCorrect
testine ekleyin.
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 bir X işareti görürsünüz.
- Ayrıca şunlara da dikkat edin:
- Tek bir başarısız onaylama, testin tamamının başarısız olmasına neden olur.
- Beklenen değer (3) ile gerçekte hesaplanan değer (2) karşılaştırılır.
- Başarısız onaylama satırına (
(ExampleUnitTest.kt:16)
) yönlendirilirsiniz.
3. adım: Araçlı bir test çalıştırın
Araçlı testler androidTest
kaynak kümesindedir.
androidTest
kaynak grubunu açın.ExampleInstrumentedTest
adlı testi çalıştır.
ExampleInstrumentedTest
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.android.architecture.blueprints.reactive",
appContext.packageName)
}
}
Yerel testten farklı olarak bu test, bir cihazda (aşağıdaki örnekte emüle edilmiş bir Pixel 2 telefonda) çalışır:
Bir cihaz bağlıysa veya bir emülatör çalışıyorsa testi emülatörde görmeniz gerekir.
Bu görevde, uygulamanızın etkin ve tamamlanmış görev istatistiklerinin yüzdesini hesaplayan getActiveAndCompleteStats
için testler yazacaksınız. Bu sayıları uygulamanın istatistikler ekranında görebilirsiniz.
1. adım: Bir test sınıfı oluşturun
main
kaynak grubunda,todoapp.statistics
içindeStatisticsUtils.kt
öğesini açın.getActiveAndCompletedStats
işlevini bulun.
StatisticsUtils.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, bir görev listesini kabul eder ve StatsResult
döndürür. StatsResult
, tamamlanan görevlerin yüzdesi ve etkin görevlerin yüzdesi olmak üzere iki sayı içeren bir veri sınıfıdır.
Android Studio, bu işlevin testlerini uygulamanıza yardımcı olacak test saplamaları oluşturma araçları sunar.
getActiveAndCompletedStats
simgesini sağ tıklayın ve Oluştur > Test'i seçin.
Test Oluştur iletişim kutusu açılır:
- Sınıf adı: bölümünü
StatisticsUtilsTest
olarak değiştirin (StatisticsUtilsKtTest
yerine; test sınıfı adında KT olmaması biraz daha iyi olur). - Diğer varsayılan değerleri koruyun. JUnit 4, uygun test kitaplığıdır. Hedef paket doğru (
StatisticsUtils
sınıfının konumunu yansıtır) ve onay kutularından herhangi birini işaretlemeniz gerekmez (bu yalnızca ek kod oluşturur ancak testinizi sıfırdan yazarsınız). - Tamam'a basın.
Hedef dizini seçin iletişim kutusu açılır:
İşleviniz matematiksel hesaplamalar yaptığından ve Android'e özgü herhangi bir kod içermediğinden yerel bir test yapacaksınız. Bu nedenle, gerçek veya emüle edilmiş bir cihazda çalıştırmanıza gerek yoktur.
- Yerel testler yazacağınız için
test
dizinini (androidTest
değil) seçin. - Tamam'ı tıklayın.
test/statistics/
içinde oluşturulanStatisticsUtilsTest
sınıfına dikkat edin.
2. adım: İlk test işlevinizi yazın
Aşağıdakileri kontrol eden bir test yazacaksınız:
- Tamamlanmış görev yoksa ve bir etkin görev varsa
- Etkin testlerin yüzdesinin %100 olması,
- ve tamamlanan görevlerin yüzdesi %0'dır.
StatisticsUtilsTest
adlı kişiyi aç.getActiveAndCompletedStats_noCompleted_returnsHundredZero
adlı bir işlev oluşturun.
StatisticsUtilsTest.kt
class StatisticsUtilsTest {
fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
// Create an active task
// Call your function
// Check the result
}
}
- Test olduğunu belirtmek için işlev adının üzerine
@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
'ı arayın.
// Call your function
val result = getActiveAndCompletedStats(tasks)
- Onaylamaları kullanarak
result
değerinin beklediğiniz değer olduğunu doğrulayın.
// Check the result
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)
Tam kod aşağıda verilmiştir.
StatisticsUtilsTest.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
simgesini sağ tıklayıp Çalıştır'ı seçin).
Şu koşulları karşılamalıdır:
3. adım: Hamcrest bağımlılığını ekleyin
Testleriniz, kodunuzun ne yaptığını gösteren bir doküman görevi gördüğünden, testlerinizin okunabilir olması önemlidir. Aşağıdaki iki iddiayı karşılaştırın:
assertEquals(result.completedTasksPercent, 0f)
// versus
assertThat(result.completedTasksPercent, `is`(0f))
İkinci iddia, insan tarafından yazılmış bir cümleye çok daha fazla benziyor. Hamcrest adlı bir onaylama çerçevesi kullanılarak yazılmıştır. Okunabilir onaylamalar yazmak için kullanabileceğiniz bir diğer iyi araç da Truth kitaplığıdır. Bu codelab'de onaylamalar yazmak için Hamcrest'i kullanacaksınız.
build.grade (Module: app)
bağlantısını açın ve aşağıdaki bağımlılığı ekleyin.
app/build.gradle
dependencies {
// Other dependencies
testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
}
Genellikle bağımlılık eklerken implementation
kullanırsınız ancak burada testImplementation
kullanıyorsunuz. Uygulamanızı tüm dünyayla paylaşmaya hazır olduğunuzda, APK'nızın boyutunu uygulamanızdaki test kodu veya bağımlılıklarla şişirmemeniz en iyisidir. Gradle yapılandırmalarını kullanarak bir kitaplığın ana koda mı yoksa test koduna mı dahil edileceğini belirleyebilirsiniz. En yaygın yapılandırmalar şunlardır:
implementation
—Bağımlılık, test kaynak kümeleri de dahil olmak üzere tüm kaynak kümelerinde kullanılabilir.testImplementation
: Bağımlılık yalnızca test kaynağı grubunda kullanılabilir.androidTestImplementation
: Bağımlılık yalnızcaandroidTest
kaynak grubunda kullanılabilir.
Hangi yapılandırmayı kullandığınız, bağımlılığın nerede kullanılabileceğini tanımlar. Şunu yazarsanız:
testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
Bu, Hamcrest'in yalnızca test kaynağı grubunda kullanılabileceği anlamına gelir. Ayrıca, Hamcrest'in nihai uygulamanıza dahil edilmemesini sağlar.
4. adım: Hamcrest'i kullanarak onaylamalar yazın
getActiveAndCompletedStats_noCompleted_returnsHundredZero()
testiniassertEquals
yerine Hamcrest'inassertThat
işlevini 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 import org.hamcrest.Matchers.`is`
özelliğini kullanabileceğinizi unutmayın.
Son test aşağıdaki kod gibi görünür.
StatisticsUtilsTest.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))
}
}
- Güncellenen testinizi çalıştırarak hâlâ çalıştığını doğrulayın.
Bu codelab'de Hamcrest'in tüm ayrıntıları öğretilmeyecektir. Daha fazla bilgi edinmek isterseniz resmi eğitime göz atın.
Bu, pratik 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 Odaklı Geliştirme programı uygulamasından türetilen bir stratejiyi kullanarak testler yazacaksınız. Test odaklı geliştirme (TDD), özellik kodunuzu önce yazmak yerine önce testlerinizi yazmanızı öneren bir programlama yaklaşımıdır. Ardından, testlerinizi geçme hedefiyle özellik kodunuzu yazarsınız.
1. Adım: Testleri yazma
Normal bir görev listeniz olduğunda test yazma:
- Tamamlanmış bir görev varsa ve etkin görev yoksa
activeTasks
yüzdesi0f
, tamamlanmış görevlerin yüzdesi ise100f
olmalıdır . - İki tamamlanmış ve üç etkin görev varsa tamamlanma yüzdesi
40f
, etkin görev yüzdesi ise60f
olmalıdır.
2. adım: Bir hata için test yazma
getActiveAndCompletedStats
için yazılan kodda hata var. Listenin boş veya null olması durumunda ne olacağını düzgün şekilde ele almadığına dikkat edin. Bu iki durumda da her iki yüzdelik değer 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ştirme yöntemini kullanırsınız. Test odaklı geliştirme aşağıdaki adımları izler.
- Given, When, Then yapısını kullanarak ve kurala uygun bir adla testi yazın.
- Testin başarısız olduğunu onaylayın.
- Testin geçmesi için gereken minimum kodu yazın.
- Bu işlemi tüm testler için tekrarlayın.
Hata düzeltmeyle başlamak yerine önce testleri yazarak başlayacaksınız. Ardından, gelecekte bu hataları yanlışlıkla yeniden eklemenizi engelleyecek testleriniz olduğunu onaylayabilirsiniz.
- Boş bir liste (
emptyList()
) varsa her iki yüzde de 0f olmalıdır. - Görevler yüklenirken bir hata oluştuysa liste
null
olur ve her iki yüzde de 0 olur. - Testlerinizi çalıştırın ve başarısız olduğunu doğrulayın:
3. Adım: Hatayı düzeltme
Testlerinizi yaptıktan sonra hatayı düzeltin.
getActiveAndCompletedStats
işlevindeki hatayı,tasks
değerinull
ise veya boşsa0f
değerini döndürerek 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 artık başarılı olduğunu doğrulayın.
TDD'yi uygulayarak ve testleri önce yazarak şunların sağlanmasına yardımcı oldunuz:
- Yeni işlevlerle her zaman ilişkili testler bulunur. Bu nedenle testleriniz, kodunuzun ne yaptığına dair doküman görevi görür.
- Testleriniz doğru sonuçları kontrol eder ve daha önce gördüğünüz hatalara karşı koruma sağlar.
Çözüm: Daha fazla test yazma
Tüm testleri ve ilgili özellik kodunu aşağıda bulabilirsiniz.
StatisticsUtilsTest.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))
}
}
StatisticsUtils.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ırmanın temellerini çok iyi öğrenmişsiniz. Ardından, temel ViewModel
ve LiveData
testlerini nasıl yazacağınızı öğreneceksiniz.
Bu codelab'in geri kalanında, çoğu uygulamada yaygın olarak kullanılan iki Android sınıfı (ViewModel
ve LiveData
) için testler yazmayı öğreneceksiniz.
TasksViewModel
için testler yazarak başlarsınız.
Tüm mantığı görünüm modelinde olan ve depo koduna dayanmayan testlere odaklanacaksınız. Depo kodu; eşzamansız kod, veritabanları ve ağ çağrıları içerir. Bunların tümü test karmaşıklığını artırır. Şimdilik bunu yapmayacak ve depodaki hiçbir şeyi doğrudan test etmeyen ViewModel işlevselliği için testler yazmaya odaklanacaksınız.
Yazacağınız test, addNewTask
yöntemi çağrıldığında yeni görev penceresini açmak için Event
'nin tetiklendiğini kontrol eder. Test edeceğiniz uygulama kodu aşağıda 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.
tasks
paketinde test etmek istediğiniz sınıfı açın.TasksViewModel.
- Kodda sınıf adını sağ tıklayın
TasksViewModel
-> Oluştur -> Test'i seçin.
- Test Oluştur ekranında, varsayılan ayarlarda değişiklik yapmadan Tamam'ı tıklayarak kabul edin.
- Hedef Dizin Seçin iletişim kutusunda test dizinini seçin.
2. adım: ViewModel testinizi yazmaya başlama
Bu adımda, addNewTask
yöntemini çağırdığınızda yeni görev penceresini açmak için Event
tetiklendiğini test etmek üzere bir görünüm modeli testi eklersiniz.
addNewTask_setsNewTaskEvent
adlı 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 bağlamı?
Test etmek için TasksViewModel
örneği oluşturduğunuzda oluşturucu, Application Context gerektirir. Ancak bu testte etkinlikler, kullanıcı arayüzü ve parçalar içeren tam bir uygulama oluşturmuyorsunuz. Peki uygulama bağlamını nasıl elde edeceksiniz?
TasksViewModelTest.kt
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(???)
AndroidX Test kitaplıkları, Uygulamalar ve Etkinlikler gibi bileşenlerin testler için tasarlanmış sürümlerini sağlayan sınıflar ve yöntemler içerir. Simüle edilmiş Android çerçeve sınıflarına(ör. Application Context) ihtiyacınız olan bir yerel testiniz olduğunda AndroidX Test'i düzgün şekilde ayarlamak için aşağıdaki adımları uygulayın:
- AndroidX Test çekirdek ve ext bağımlılıklarını ekleyin.
- Robolectric Testing library bağımlılığını ekleyin.
- Sınıfa AndroidJUnit4 test çalıştırıcısıyla not ekleme
- AndroidX Test kodu yazma
Bu adımları tamamlayacak ve ardından birlikte ne yaptıklarını anlayacaksınız.
3. Adım: Gradle bağımlılıklarını ekleyin
- Temel AndroidX Test ve ext 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.
app/build.gradle
// AndroidX Test - JVM testing
testImplementation "androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion"
testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"
testImplementation "org.robolectric:robolectric:$robolectricVersion"
4. Adım. JUnit Test Runner'ı ekleme
- Test sınıfınızın üzerine
@RunWith(AndroidJUnit4::class)
ekleyin.
TasksViewModelTest.kt
@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
// Test code
}
5. Adım: AndroidX Test'i kullanma
Bu noktada AndroidX Test kitaplığını kullanabilirsiniz. Bu, bir uygulama bağlamı alan ApplicationProvider.getApplicationContex
t
yöntemini içerir.
- AndroidX test kitaplığındaki
ApplicationProvider.getApplicationContext()
öğesini kullanarakTasksViewModel
oluşturun.
TasksViewModelTest.kt
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
tasksViewModel
numaralı telefondanaddNewTask
kullanıcısını ara.
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ığını onaylamak için testinizi çalıştırın.
Kavram: AndroidX Test nasıl çalışır?
AndroidX Test nedir?
AndroidX Test, test için kullanılan bir kitaplık koleksiyonudur. Uygulamalar ve Etkinlikler gibi bileşenlerin testler için tasarlanmış sürümlerini sunan sınıflar ve yöntemler içerir. Örneğin, yazdığınız bu kod, uygulama bağlamını almak için kullanılan bir AndroidX Test işlevine örnektir.
ApplicationProvider.getApplicationContext()
AndroidX Test API'lerinin avantajlarından biri, hem yerel testler hem de enstrümanlı testler için çalışacak şekilde oluşturulmuş olmasıdır. Bu özellik sayesinde:
- Aynı testi yerel test veya araçlı test olarak çalıştırabilirsiniz.
- Yerel testler ile enstrümantasyonlu 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 ve testler yine de çalışır. getApplicationContext()
, yerel test veya enstrümantasyonlu test olarak çalıştırılmasına bağlı olarak biraz farklı işler:
- Bu bir enstrümanlı testse öykünücü başlatıldığında veya gerçek bir cihaza bağlandığında sağlanan gerçek uygulama bağlamını alır.
- Yerel bir testse simüle edilmiş bir Android ortamı kullanılır.
Robolectric nedir?
AndroidX Test'in yerel testler için kullandığı simüle edilmiş Android ortamı Robolectric tarafından sağlanır. Robolectric, testler için simüle edilmiş bir Android ortamı oluşturan ve bir emülatörü başlatmaktan veya bir cihazda çalıştırmaktan daha hızlı çalışan bir kitaplıktır. Robolectric bağımlılığı 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ı olmadan testleriniz çalışmaz. JUnit tarafından sağlanan ve otomatik olarak aldığınız varsayılan bir test çalıştırıcı vardır. @RunWith
, varsayılan test çalıştırıcıyı değiştirir.
AndroidJUnit4
test çalıştırıcısı, AndroidX Test'in testinizi, enstrümantasyonlu veya yerel testler olmasına bağlı olarak farklı şekilde çalıştırmasına olanak tanır.
6. Adım: Robolectric uyarılarını düzeltme
Kodu çalıştırdığınızda Robolectric'in kullanıldığını fark edeceksiniz.
AndroidX Test ve AndroidJunit4 test çalıştırıcısı sayesinde bu işlem, tek bir satır Robolectric kodu yazmanıza gerek kalmadan 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 manifestinin kullanılması için gradle dosyanıza aşağıdaki satırı ekleyin. includeAndroidResources seçeneği, birim testlerinizde AndroidManifest dosyanız da dahil olmak üzere Android kaynaklarına erişmenize olanak tanır.
app/build.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 hedef ve derleme SDK'nızı 28'de tutun.
Özet olarak:
- Saf görünüm modeli testleri, kodları genellikle Android gerektirmediğinden
test
kaynak kümesine eklenebilir. - Uygulamalar ve Etkinlikler gibi bileşenlerin test sürümlerini almak için AndroidX test kitaplığını kullanabilirsiniz.
test
kaynak kümenizde simüle edilmiş Android kodu çalıştırmanız gerekiyorsa Robolectric bağımlılığını 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 tamamlanmadı (henüz bir onaylama ifadesi yazmadınız, yalnızca // TODO test LiveData
yazıyor). Bir sonraki adımda LiveData
ile onaylama ifadeleri yazmayı öğreneceksiniz.
Bu görevde, LiveData
değerini doğru şekilde onaylamayı öğreneceksiniz.
addNewTask_setsNewTaskEvent
görünüm modeli testi olmadan kaldığınız yer.
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
test etmek için iki işlem yapmanız önerilir:
InstantTaskExecutorRule
hareketini kullanınLiveData
gözlemi yapma
1. Adım: InstantTaskExecutorRule'u kullanma
InstantTaskExecutorRule
, JUnit kuralıdır. @get:Rule
ek açıklamasıyla birlikte kullanıldığında, 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ı görüntülemek üzere Command+B klavye kısayolunu kullanabilirsiniz).
Bu kural, test sonuçlarının eşzamanlı olarak ve tekrarlanabilir bir sırada gerçekleşmesi için tüm Architecture Components ile ilgili arka plan işlerini aynı iş parçacığında çalıştırır. LiveData'nın test edilmesini içeren testler yazdığınızda bu kuralı kullanın.
- Architecture Components çekirdek test kitaplığı (bu kuralı içerir) için Gradle bağımlılığını ekleyin.
app/build.gradle
testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
TasksViewModelTest.kt
uygulamasını açInstantTaskExecutorRule
öğesiniTasksViewModelTest
sınıfına ekleyin.
TasksViewModelTest.kt
class TasksViewModelTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
// Other code...
}
2. adım: LiveDataTestUtil.kt sınıfını ekleme
Sonraki adımınız, test ettiğiniz LiveData
öğesinin gözlemlendiğinden emin olmaktır.
LiveData
kullanırken genellikle bir etkinlik veya parça (LifecycleOwner
) LiveData
'yı gözlemler.
viewModel.resultLiveData.observe(fragment, Observer {
// Observer code here
})
Bu gözlem önemlidir. Şunları yapmak için LiveData
'da etkin gözlemcilerinizin olması gerekir:
onChanged
etkinliklerini tetikleyebilir.- Dönüşümleri tetikleme
Görünüm modelinizin LiveData
için beklenen LiveData
davranışını elde etmek istiyorsanız LiveData
ile LifecycleOwner
değerini gözlemlemeniz gerekir.
Bu durum bir sorun teşkil eder: TasksViewModel
testinizde LiveData
öğenizi gözlemleyebileceğiniz bir etkinlik veya parça yoktur. Bu sorunu çözmek için observeForever
yöntemini kullanabilirsiniz. Bu yöntem, LifecycleOwner
'e ihtiyaç duymadan LiveData
'ün sürekli olarak gözlemlenmesini sağlar. observeForever
yaptığınızda gözlemcinizi kaldırmayı unutmamalısınız. Aksi takdirde gözlemci sızıntısı riskiyle karşı karşıya kalırsınız.
Bu, aşağıdaki koda benzer. İnceleyin:
@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)
}
}
Testte tek bir LiveData
gözlemlemek için çok fazla standart kod yazmanız gerekir. Bu standart metinden kurtulmanın birkaç yolu vardır. Gözlemci eklemeyi kolaylaştırmak için LiveDataTestUtil
adlı bir uzantı işlevi oluşturacaksınız.
test
kaynak kümenizdeLiveDataTestUtil.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 yöntem oldukça karmaşıktır. Bu işlev, bir gözlemci ekleyen, LiveData
değerini alan ve ardından gözlemciyi temizleyen getOrAwaitValue
adlı bir Kotlin uzantı işlevi oluşturur. Bu işlev, yukarıda gösterilen observeForever
kodunun kısa ve yeniden kullanılabilir bir sürümüdür. Bu sınıfın tam açıklaması için blog yayınımıza göz atın.
3. Adım: Onaylama yazmak için getOrAwaitValue'yu kullanın
Bu adımda getOrAwaitValue
yöntemini kullanır ve newTaskEvent
tetiklendiğini kontrol eden bir assert ifadesi yazarsınız.
getOrAwaitValue
kullanaraknewTaskEvent
içinLiveData
değerini alın.
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
- Değerin boş olmadığını onaylayın.
assertThat(value.getContentIfNotHandled(), (not(nullValue())))
Tam test aşağıdaki koda benzemelidir.
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 testin geçmesini izleyin.
Test yazmayı öğrendiğinize göre şimdi kendi testinizi yazın. Bu adımda, öğrendiğiniz becerileri kullanarak başka bir TasksViewModel
testi yazmayı deneyin.
1. Adım: Kendi ViewModel testinizi yazma
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 olarak
addNewTask_setsNewTaskEvent()
kullanarakTasksViewModelTest
içindesetFilterAllTasks_tasksAddViewVisible()
adlı bir test yazın. Bu test, filtreleme modunuALL_TASKS
olarak ayarlar vetasksAddViewVisible
LiveData'nıntrue
olduğunu onaylar.
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
enum'ıALL_TASKS.
'dır. - Görev ekleme düğmesinin görünürlüğü
LiveData
tasksAddViewVisible.
tarafından kontrol edilir.
- Testinizi çalıştırın.
2. adım: Testinizi çözümle karşılaştırma
Çö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:
- Aynı AndroidX
ApplicationProvider.getApplicationContext()
ifadesini kullanaraktasksViewModel
oluşturursunuz. setFiltering
yöntemini çağırıpALL_TASKS
filtre türü enum'ını iletirsiniz.getOrAwaitNextValue
yöntemini kullanaraktasksAddViewVisible
değerinin doğru olduğunu kontrol edersiniz.
3. Adım: @Before kuralı ekleme
Her iki testin başında bir TasksViewModel
tanımladığınıza dikkat edin.
TasksViewModelTest
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
Birden fazla test için tekrarlanan kurulum kodunuz olduğunda, kurulum yöntemi oluşturmak ve tekrarlanan kodu kaldırmak için @Before ek açıklamasını kullanabilirsiniz. Bu testlerin tümü TasksViewModel
öğesini test edeceğinden ve bir görünüm modeli gerektirdiğinden bu kodu @Before
bloğuna 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ünüm modeli oluşturma kodunu
setupViewModel
konumuna 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 birlikte:
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
Bu durumda, tüm testler için aynı örnek kullanılır. Her testte, test edilen öğenin (bu durumda ViewModel) yeni bir örneği olması gerektiğinden bu durumdan kaçınmalısınız.
TasksViewModelTest
için nihai kodunuz 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 son kod arasındaki farkı görmek için burayı tıklayın.
Tamamlanmış 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, depoyu Zip dosyası olarak indirebilir, dosyayı açıp Android Studio'da açabilirsiniz.
Bu codelab'de aşağıdaki konular ele alındı:
- Android Studio'dan test çalıştırma
- Yerel (
test
) ve enstrümantasyon testleri (androidTest
) arasındaki fark. - JUnit ve Hamcrest kullanarak yerel birim testleri yazma
- AndroidX Test Kitaplığı ile ViewModel testleri ayarlama.
Udacity kursu:
Android geliştirici belgeleri:
- Uygulama mimarisi kılavuzu
- JUnit4
- Hamcrest
- Robolectric Testing library
- AndroidX Test Kitaplığı
- AndroidX Architecture Components Core Test Library
- kaynak grupları
- Komut satırından test etme
Videolar:
Diğer:
Bu kurstaki diğer codelab'lerin bağlantıları için Advanced Android in Kotlin codelab'lerinin açılış sayfasına bakın.