Android Studio 단위 테스트 : 데이터 (입력) 파일 읽기


96

단위 테스트에서 경로를 하드 코딩하지 않고 내 (데스크톱) 파일 시스템의 json 파일에서 데이터를 어떻게 읽을 수 있습니까?

정적 문자열을 만드는 대신 파일에서 테스트 입력 (내 구문 분석 방법에 대한)을 읽고 싶습니다.

파일은 내 단위 테스트 코드와 같은 위치에 있지만 필요한 경우 프로젝트의 다른 위치에 배치 할 수도 있습니다. Android Studio를 사용하고 있습니다.


3
IOUtils.toString (this.getClass (). getResourceAsStream ( "test_documents.json"), "UTF-8") 거의 모든 조합을 시도했지만 항상 null을 반환합니다. 아마도 파일이 항아리에 포함되지 않기 때문일 것입니다.
Frank

Android 에뮬레이터 / 기기와 관련된 단위 테스트에 대해 이야기하고 있습니까?
AndroidEx


@Frank는 어디에 배치 test_documents.json합니까? 자산 디렉토리?
akhy

예, 에뮬레이터 / 장치를 포함하지 않는 새로운 단위 테스트 지원에 대해 이야기하고 있습니다. 라이브 APK와 함께 패키징되기 때문에 자산 디렉토리에 배치하지 않았습니다. 테스트 (java) 파일과 같은 폴더에 저장했습니다.
Frank

답변:


149

android-gradle-plugin버전 에 따라 :

1. 버전 1.5 이상 :

json 파일을 넣고 다음 src/test/resources/test.json과 같이 참조하십시오.

classLoader.getResource("test.json"). 

gradle 수정이 필요하지 않습니다.

2. 1.5 미만 버전 : (또는 위의 솔루션이 작동하지 않는 경우)

  1. Android Gradle 플러그인 버전 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
대박! 악기 테스트가없는 편집은 매력처럼 작동합니다. 감사합니다!
Frank

4
좋은 해결책이지만 항상 작동하지는 않습니다. 정리 작업을 실행 한 다음 testDebug를 실행하면 실패합니다. 기본적으로 개발자는 testDebug 전에 assembleDebug 작업을 실행해야 함을 알아야합니다. 이것을 개선하기위한 제안이 있습니까?
joaoprudencio 2015

18
Android 플러그인 1.5.0이 포함 된 AndroidStudio 1.5를 사용하여 여기에 json 파일을 배치 src/test/resources/test.json하고 classLoader.getResource("test.json"). gradle 수정이 필요하지 않습니다. 내부의 중첩 폴더 resources도 작동합니다.
Sergii Pechenizkyi

6
불완전한 답변입니다. 무엇입니까 classLoader? 이 코드 줄을 어디에 배치할까요? 반환 결과로 무엇을 할 수 있습니까?. 더 완전한 코드를 제공하십시오. -1
voghDev

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

그것은 함께 일했습니다

  • 안드로이드 스튜디오 1.5.1
  • gradle 플러그인 1.3.1

이 날 여기 내 질문을 참조하십시오 작동하지 않습니다 stackoverflow.com/questions/36295824/...
타일러 파프

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 2010 년

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

매력처럼 일했다!
Amit Bhandari 2019

15

제 경우 해결책은 gradle 파일에 추가하는 것이 었습니다.

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

AS 2.3.1에 의해 모든 것이 발견 된 후

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

1
나는 매우 비슷한 일을했다 (Kotlin) : 1. 폴더와 파일을 다음 위치에 만듭니다. root/app/src/test/resources/test.json 2. 다음과 같은 데이터를 읽습니다.val jsonFile = ClassLoader.getSystemResource("test.json").readText()
jj.

8

Android Studio의 테스트 리소스에 많은 문제가 있었기 때문에 명확성을 위해 몇 가지 테스트를 설정했습니다. 내 mobile(Android Application) 프로젝트에서 다음 파일을 추가했습니다.

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

동일한 루트 프로젝트에 .NET 이라는 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 스튜디오 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를 통해서는 작동 하지 않습니다.
Mark McKenna

6

실행-> 구성 편집-> JUnit으로 이동 한 다음 단위 테스트에 대한 실행 구성을 선택하면 '작업 디렉터리'설정이 있습니다. json 파일이있는 곳을 가리켜 야합니다. 이로 인해 다른 테스트가 중단 될 수 있습니다.


this.getClass (). getResourceAsStream (test.json)을 사용하는 것보다? 프로젝트의 루트에 파일을 추가했지만 여전히 파일을 찾지 못했습니다.
Frank

new File()또는 이와 유사한 방법을 사용하여 파일을로드하는 데 사용할 수 있지만 위에서 설명한 클래스 경로로드 방법에서는 직접 작동하지 않습니다. 또한 각각의 새로운 실행 구성은 작업 디렉토리를 설정해야하고 기본적으로 AS 및 Gradle 명령 줄은 서로 다른 작업 디렉토리를 사용하기를 원하기 때문에 약간 까다 롭습니다. 이러한 고통
Mark McKenna

5

여기에 내 결과를 추가해야하지만. 이것이 조금 오래되었다는 것을 알고 있지만 src / test / resources 디렉토리가 없지만 전체 프로젝트에 대해 하나의 리소스 디렉토리 만있는 Gradle의 최신 버전의 경우이 줄을 Gradle 파일에 추가해야합니다.

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

이렇게하면 다음을 통해 리소스에 액세스 할 수 있습니다.

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

나는 이것을 찾고 있었지만 답을 찾을 수 없어서 다른 사람들을 돕기로 결정했습니다.


1

실제로 이것은 Instrumentation Tests (Android Studio 버전 3.5.3 , Android Gradle Plugin 버전 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.