Android Studioユニットテスト:データ(入力)ファイルの読み取り


96

単体テストで、パスをハードコーディングせずに、(デスクトップ)ファイルシステムのjsonファイルからデータを読み取るにはどうすればよいですか?

静的文字列を作成するのではなく、ファイルからテスト入力(解析メソッド用)を読み取りたいのですが。

ファイルはユニットテストコードと同じ場所にありますが、必要に応じてプロジェクト内の別の場所に配置することもできます。Android Studioを使用しています。


3
私はIOUtils.toString(this.getClass()。getResourceAsStream( "test_documents.json")、 "UTF-8")とほぼすべての組み合わせを試しましたが、常にnullを返します。おそらくファイルがjarに含まれないためです。
フランク

Androidエミュレーター/デバイスを含むユニットテストについて話しているのですか?
AndroidEx 2015

Android777 @私たちはAndroidのスタジオの最新バージョンで導入された新しいユニットテストのサポートについて話していると思うtools.android.com/tech-docs/unit-testing-support
akhy

@フランクはどこに置きtest_documents.jsonますか?アセットディレクトリ?
akhy 2015

はい、私たちは、エミュレーター/デバイスを含まない、新しい単体テストのサポートについて話しています。ライブのapkでパッケージ化されるため、アセットディレクトリには配置しませんでした。テスト(java)ファイルと同じフォルダーに配置しました。
フランク

回答:


149

android-gradle-pluginバージョンによって:

1.バージョン1.5以降:

jsonファイルを入れてsrc/test/resources/test.json、それを次のように参照するだけです

classLoader.getResource("test.json"). 

Gradleの変更は必要ありません。

2. 1.5未満のバージョン:(または何らかの理由で上記の解決策が機能しない場合)

  1. 少なくともAndroid Gradle Pluginバージョン1.1を使用していることを確認してください。リンクに従って、Android Studioを正しくセットアップします。

  2. testディレクトリを作成します。単体テストクラスをjavaディレクトリに配置し、リソースファイルをresディレクトリに配置します。Android Studioは次のようにマークする必要があります。

    ここに画像の説明を入力してください

  3. gradleリソースをクラスディレクトリにコピーして、それらを次の場所から見えるようにするタスクを作成しますclassloader

    android{
       ...
    }
    
    task copyResDirectoryToClasses(type: Copy){
        from "${projectDir}/src/test/res"
        into "${buildDir}/intermediates/classes/test/debug/res"
    }
    
    assembleDebug.dependsOn(copyResDirectoryToClasses)
  4. これで、このメソッドを使用Fileしてファイルリソースの参照を取得できます。

    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. クラス全体または特定のテストメソッドでユニットテストをCtrl+ Shift+ F10で実行します。

1
驚くばかり!あなたの編集は器械テストなしで、魅力のように機能します、ありがとう!
フランク

4
これは良い解決策ですが、常に機能するとは限りません。クリーンタスクを実行してからtestDebugを実行すると失敗します。基本的に、開発者はtestDebugの前に、assembleDebugタスクを実行する必要があることを知る必要があります。これを改善するための提案はありますか?
joaoprudencio 2015

18
AndroidStudio 1.5とAndroidプラグイン1.5.0を使用して、jsonファイルをここに配置しsrc/test/resources/test.json、として参照しますclassLoader.getResource("test.json")。Gradleの変更は必要ありません。内部のネストされたフォルダresourcesも機能しています。
Sergii Pechenizkyi 2015年

6
不完全な答え。なにclassLoader?このコード行をどこに配置しますか?返された結果を使って何ができますか?より完全なコードを入力してください。-1
voghDev 2017年

3
./src/test/resources/file.txtKotlinで読むには:TestClassName::class.java.getResource("/file.txt")!!.readText()
Erik

76

ローカルユニットテスト(インストゥルメンテーションテストに対して)の場合、src/test/resourcesclassLoaderを使用してファイルを配置し、読み取ることができます。たとえば、次のコードmyFile.txtはリソースディレクトリのファイルを開きます。

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

それはで働いた

  • Android Studio 1.5.1
  • Gradleプラグイン1.3.1

これは私のために働いていない、ここで私の質問を参照してください。stackoverflow.com/questions/36295824/...
タイラーPfaff事件

5
これは、「src / test / res」から「src / test / resources」に変更したときに機能しました。Android Studio 2.0 RC 3を使用して、gradle:2.0.0-rc3
Alex Bravo

期待どおりに動作しました。しかし、ファイルが「src / test / resources /」の下にない場合でも、テストはパスしています。たとえば、「rules.xml」ですが、この場合、InputStreamはnullになります。
anand krish 2017

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

魅力のように働いた!
アミットバンダリ

15

私の場合、解決策はgradleファイルに追加することでした

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

その後、すべてがAS 2.3.1によって検出されました

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

私は非常に似たようなことをしました(Kotlin):1.次の場所にフォルダーとファイルを作成します:root/app/src/test/resources/test.json 2.次のようにデータを読み取ります:val jsonFile = ClassLoader.getSystemResource("test.json").readText()
jj。

8

Android Studioのテストリソースに多くの問題があったため、わかりやすくするためにいくつかのテストを設定しました。私の mobile(Androidアプリケーション)プロジェクトに次のファイルを追加しました。

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

テストクラス(すべてのテストに合格):

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"));

同じルートプロジェクトにと呼ばれるJava(Androidではない)プロジェクトがありdataます。同じプロジェクトをデータプロジェクトに追加した場合:

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

その後、Android Studioから実行すると、上記のすべてのテストが失敗し./gradlew data:testますが、コマンドラインでを渡します。それを回避するには、このハックを使用します(Groovy内)

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

使用法: resource('/test.txt')

Android Studio 2.3、Gradle 3.3


すばらしい回答です(45分の検索後😌)。それはいくつかの問題の核心に到達し、テスト自体を使用して結果を簡単に複製できるようにします。Fwiw、AS 2.3.1、Gradle 2.3.1では、getClassLoader()バージョンは期待どおりに機能します。つまり、Android Studioから、および私のmacOSマシンのコマンドラインから、そしてLinux CIサーバー(CircleCI)から実行されるファイルを見つけます。だから私はそれを使って、Gradle 3.3が後でそれを壊さないことを願っています...
mm2001

いいね!ここで同じリソースの読み込みの問題が発生しています。AS 2.3.2、Gradle 3.3。テストbuild/resources/testはインタラクティブなクラスパスに含まれていないため、コマンドラインからは機能しますが、ASからは機能しません。
マークマッケナ

6

「実行」->「構成の編集」->「JUnit」に移動し、ユニットテストの実行構成を選択すると、「作業ディレクトリ」設定があります。それはあなたのjsonファイルがどこにあっても指す必要があります。これは他のテストを壊す可能性があることに注意してください。


そしてthis.getClass()。getResourceAsStream(test.json)を使用するよりも?ファイルをプロジェクトのルートに追加しましたが、ファイルはまだ見つかりません。
フランク

これはnew File()またはを使用してファイルをロードするために使用できますが、上記のクラスパスのロード方法では直接動作しません。別の作業dirsにを使用するようにそれはそれぞれの新しい実行構成は、作業ディレクトリを設定する必要があるため、ビットトリッキーだし、デフォルトでASとGradleのコマンドライン...などの痛み
マーク・マッケンナ

4

ここに私の調査結果を追加する必要がありますが。私はこれが少し古いことを知っていますが、src / test / resourcesディレクトリがなく、プロジェクト全体に対して1つの単一のリソースディレクトリしかない新しいバージョンのGradleの場合、この行をGradleファイルに追加する必要があります。

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

これにより、次の方法でリソースにアクセスできます。

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

私はこれを探していて、答えを見つけることができなかったので、ここで他の人を助けることにしました。


1

実際、これはインストルメンテーションテストで機能したものです(Android Studioバージョン3.5.3、Android Gradleプラグインバージョン3.5.3、Gradleバージョン6.0.1を実行しています)。

  1. ファイルをsrc/androidTest/assetsフォルダに入れます
  2. テストファイルで:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.