Android Studio birim testi: veri (giriş) dosyasını oku


99

Bir birim testinde, yolu kodlamadan (masaüstü) dosya sistemimdeki bir json dosyasından verileri nasıl okuyabilirim?

Statik Dizeler oluşturmak yerine bir dosyadan test girdisini (ayrıştırma yöntemlerim için) okumak istiyorum.

Dosya, birim test kodumla aynı konumdadır, ancak gerekirse projede başka bir yere de yerleştirebilirim. Android Studio kullanıyorum.


3
IOUtils.toString (this.getClass (). GetResourceAsStream ("test_documents.json"), "UTF-8") ile hemen hemen her kombinasyonu denedim, her zaman boş döndürüyor. Muhtemelen dosyalar kavanoza dahil edilmeyeceği içindir.
Frank

Android emülatörü / cihazı içeren birim testlerinden mi bahsediyoruz?
AndroidEx

@ Android777 Sanırım Android Studio araçlarının
akhy

@Frank nereye yerleştirirsiniz test_documents.json? varlıklar dizini?
akhy

Evet, emülatör / cihazı içermeyen yeni birim test desteğinden bahsediyoruz. Bunu varlıklar dizinine koymadım çünkü o zaman canlı apk ile paketleniyor. Test (java) dosyalarıyla aynı klasöre yerleştirdim.
Frank

Yanıtlar:


152

android-gradle-pluginVersiyona bağlı olarak :

1. sürüm 1.5 ve üzeri:

Sadece json dosyasını konumuna koyun src/test/resources/test.jsonve

classLoader.getResource("test.json"). 

Kademeli modifikasyona gerek yoktur.

2. 1.5'in altındaki sürüm : (veya herhangi bir nedenle yukarıdaki çözüm çalışmazsa)

  1. En az Android Gradle Plugin sürüm 1.1 kullandığınızdan emin olun . Android Studio'yu doğru şekilde kurmak için bağlantıyı takip edin.

  2. testDizin oluşturun . Birim test sınıflarını javadizine koyun ve kaynaklar dosyanızı resdizine yerleştirin. Android Studio bunları aşağıdaki gibi işaretlemelidir:

    görüntü açıklamasını buraya girin

  3. gradleKaynakları aşağıdakiler için görünür kılmak üzere sınıflar dizinine kopyalamak için görev oluşturun classloader:

    android{
       ...
    }
    
    task copyResDirectoryToClasses(type: Copy){
        from "${projectDir}/src/test/res"
        into "${buildDir}/intermediates/classes/test/debug/res"
    }
    
    assembleDebug.dependsOn(copyResDirectoryToClasses)
    
  4. Artık Filedosya kaynağı için referans almak için bu yöntemi kullanabilirsiniz :

    private static File getFileFromPath(Object obj, String fileName) {
        ClassLoader classLoader = obj.getClass().getClassLoader();
        URL resource = classLoader.getResource(fileName);
        return new File(resource.getPath());
    }
    
    @Test
    public void fileObjectShouldNotBeNull() throws Exception {
        File file = getFileFromPath(this, "res/test.json");
        assertThat(file, notNullValue());
    }
    
  5. Birim testini Ctrl+ Shift+ F10ile tüm sınıfta veya özel test yönteminde çalıştırın.

1
Harika! Düzenlemeniz enstrüman testleri olmadan bir cazibe gibi çalışıyor, teşekkürler!
Frank

4
Güzel bir çözüm ama her zaman işe yaramıyor. Temiz görevi çalıştırırsanız ve ardından testDebug çalıştırırsanız başarısız olur. Temel olarak geliştiricinin testDebug'dan önce assembleDebug görevini çalıştırması gerektiğini bilmesi gerekir. Bunu iyileştirmek için herhangi bir öneriniz var mı?
joaoprudencio

19
Android eklentisi 1.5.0 ile AndroidStudio 1.5 ile json dosyanızı buraya yerleştirin src/test/resources/test.jsonve classLoader.getResource("test.json"). Kademeli modifikasyona gerek yoktur. İç içe geçmiş klasörler resourcesde çalışıyor.
Sergii Pechenizkyi

6
Eksik cevap. Nedir classLoader? bu kod satırını nereye yerleştirmelisiniz? dönüş sonucuyla ne yapabilirsiniz? Lütfen daha eksiksiz bir kod sağlayın. -1
voghDev

3
./src/test/resources/file.txtKotlin'de okumak için:TestClassName::class.java.getResource("/file.txt")!!.readText()
Erik

79

Yerel birim testleri için (enstrümantasyon testlerine karşı), dosyaları src/test/resourcesclassLoader kullanarak altına koyabilir ve okuyabilirsiniz. Örneğin, aşağıdaki kod myFile.txt, kaynaklar dizinindeki dosyayı açar .

InputStream in = this.getClass().getClassLoader().getResourceAsStream("myFile.txt");

İle çalıştı

  • Android Studio 1.5.1
  • gradle eklentisi 1.3.1

Bu benim için çalışmıyor lütfen soruma buradan bakın stackoverflow.com/questions/36295824/…
Tyler Pfaff

5
Bu, "src / test / res" yerine "src / test / kaynaklar" olarak değiştirdiğimde işe yaradı. Android Studio 2.0 RC 3'ü kullanma, gradle: 2.0.0-rc3
Alex Bravo

beklendiği gibi çalıştı. Ancak dosya "src / test / kaynaklar /" altında kullanılmasa bile test başarılı oluyor, örneğin: "rules.xml", ancak bu durumda InputStream boşa çıkıyor.
anand krish

4
kotlin:val myFile = ClassLoader.getSystemResource("myFile.txt").readText()
jj.

Cazibe gibi çalıştı!
Amit Bhandari

15

Benim durumumda çözüm, gradle dosyasına eklemekti

sourceSets {
    test.resources.srcDirs += 'src/unitTests/resources'
  } 

Ondan sonra her şey AS 2.3.1 tarafından bulundu

javaClass.classLoader.getResourceAsStream("countries.txt")

1
Çok benzer bir şey yaptım (Kotlin): 1. klasör ve dosya oluşturun: root/app/src/test/resources/test.json 2. Verileri şu şekilde okuyun:val jsonFile = ClassLoader.getSystemResource("test.json").readText()
jj.

8

Android Studio'daki test kaynakları ile ilgili pek çok sorun yaşadım, bu yüzden netlik sağlamak için birkaç test yaptım. Benim içinde mobile(Android Uygulama) projesi aşağıdaki dosyaları ekledi:

mobile/src/test/java/test/ResourceTest.java
mobile/src/test/resources/test.txt
mobile/src/test/resources/test/samePackage.txt

Test sınıfı (tüm testler geçer):

assertTrue(getClass().getResource("test.txt") == null);
assertTrue(getClass().getResource("/test.txt").getPath().endsWith("test.txt"));
assertTrue(getClass().getResource("samePackage.txt").getPath().endsWith("test/samePackage.txt"));
assertTrue(getClass().getResource("/test/samePackage.txt").getPath().endsWith("test/samePackage.txt"));
assertTrue(getClass().getClassLoader().getResource("test.txt").getPath().endsWith("test.txt"));
assertTrue(getClass().getClassLoader().getResource("test/samePackage.txt").getPath().endsWith("test/samePackage.txt"));

Aynı kök projede adında bir Java (Android değil) projem var data. Aynı dosyaları veri projesine eklersem:

data/src/test/java/test/ResourceTest.java
data/src/test/resources/test.txt
data/src/test/resources/test/samePackage.txt

Sonra bunları Android Studio'dan çalıştırırsam yukarıdaki tüm testler başarısız olur, ancak komut satırından ile geçerler ./gradlew data:test. Bunu aşmak için bu hack'i kullanıyorum (Groovy'de)

def resource(String path) {
    getClass().getResource(path) ?:
            // Hack to load test resources when executing tests from Android Studio
            new File(getClass().getClassLoader().getResource('.').path
                    .replace('/build/classes/test/', "/build/resources/test$path"))
}

Kullanım: resource('/test.txt')

Android Studio 2.3, Gradle 3.3


Harika cevap (45 dakikalık aramadan sonra 😌). Birkaç konunun özüne iner ve testlerin kendisini kullanarak sonuçları çoğaltmayı kolaylaştırır. Fwiw, AS 2.3.1, Gradle 2.3.1'de getClassLoader()sürümler beklendiği gibi çalışır. Yani, hem Android Studio hem de macOS makinemdeki komut satırından ve Linux CI sunucusunda (CircleCI) çalışan dosyaları bulurlar. Öyleyse bununla gidiyorum ve Gradle 3.3'ün daha sonra kırılmamasını umuyorum ...
mm2001

Güzel! Burada aynı kaynak yükleme sorununu görüyorum. AS 2.3.2, Gradle 3.3. Testler build/resources/test, etkileşimli sınıf yoluna dahil edilmediğinden komut satırından çalışır ancak AS aracılığıyla çalışmaz.
Mark McKenna

6

Çalıştır -> Yapılandırmaları düzenle -> JUnit'e gidip birim testleriniz için çalıştırma yapılandırmasını seçerseniz, bir 'Çalışma dizini' ayarı vardır. Bu, json dosyanızın olduğu yeri göstermelidir. Bunun diğer testleri bozabileceğini unutmayın.


ve this.getClass (). getResourceAsStream (test.json)? Dosyaları oraya ekledim, projenin kök dizinine hala dosyaları bulamıyor.
Frank

Bu, dosyaları kullanarak new File()veya benzer şekilde yüklemek için kullanılabilir , ancak yukarıda açıklanan sınıf yolu yükleme yöntemiyle doğrudan çalışmaz. Bu biraz da zor çünkü her yeni çalıştırma yapılandırmasının çalışma dizinini ayarlaması gerekiyor ve varsayılan olarak AS ve Gradle komut satırı farklı çalışma dizinleri kullanmayı seviyor ... çok acı
Mark McKenna

6

Bulgularımı buraya eklemem gerektiğini düşünüyorum. Bunun biraz eski olduğunu biliyorum ama src / test / kaynaklar dizininin YOK olduğu, ancak tüm proje için yalnızca tek bir kaynak dizininin olduğu Gradle'ın daha yeni sürümleri için, bu satırı Gradle dosyanıza eklemelisiniz.

android {
   testOptions {
      unitTests {
         includeAndroidResources = true
      }
    }
}

Bunu yaparak kaynağınıza şununla erişebilirsiniz:

 this.getClass().getClassLoader().getResourceAsStream(fileName);

Bunu arıyordum ve bir cevap bulamadım, bu yüzden burada başkalarına yardım etmeye karar verdim.


teşekkürler Raphael Ayres. Bu en çok oylanan yorum olmalıdır. Ayrıca, kaynak dizininizi src / test / altında oluşturmanız gerekir, böylece src / test / resources / ... 'a sahip olacaksınız
Martin Nowosad

2

Aslında, Enstrümantasyon Testleri ile benim için işe yarayan şey buydu (Android Studio sürüm 3.5.3 , Android Gradle Eklentisi sürüm 3.5.3 , Gradle sürüm 6.0.1 ):

  1. Dosyalarınızı src/androidTest/assetsklasöre koyun
  2. Test dosyanızda:

InputStream is = InstrumentationRegistry.getInstrumentation().getContext().getAssets().open("filename.txt");

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.