2013-05-20 4 views
30

Robolectric 테스트를 새로운 Gradle Android 빌드 시스템과 함께 실행하려고하는데, 주 ​​프로젝트의 리소스에 액세스 할 수 없습니다. Robolectric with Gradle : 리소스를 찾을 수 없습니다.

은 내가 javaandroid Gradle을 플러그인 간의 충돌을 방지하기 위해 두 개의 별도의 프로젝트로 빌드를 분할, 그래서 디렉토리 구조는 다음과 거의 같습니다

. 
├── build.gradle 
├── settings.gradle 
├── mainproject 
│   ├── build 
│   │   ├── classes 
│   │   │   └── debug 
│   ├── build.gradle 
│   └── src 
│    └── main 
│     ├── AndroidManifest.xml 
│     └── ... 
└── test 
    ├── build.gradle 
    └── src 
       └── test 
        └── java 
         └── ... 
       └── test 
        ├── MainActivityTest.java 
        ├── Runner.java 
        ├── ServerTestCase.java 
        └── StatusFetcherTest.java 

test/에서 build.gradle은 다음과 같습니다

buildscript { 
    repositories { 
     mavenCentral() 
    } 

    dependencies { 
     classpath 'com.stanfy.android:gradle-plugin-java-robolectric:2.0' 
    } 
} 

apply plugin: 'java-robolectric' 

repositories {...} 

javarob { 
    packageName = 'com.example.mainproject' 
} 

test { 
    dependsOn ':mainproject:build' 
    scanForTestClasses = false 
    include "**/*Test.class" 
    // Oh, the humanity! 
    def srcDir = project(':mainproject').android.sourceSets.main.java.srcDirs.toArray()[0].getAbsolutePath() 
    workingDir srcDir.substring(0, srcDir.lastIndexOf('/')) 
} 

project(':mainproject').android.sourceSets.main.java.srcDirs.each {dir -> 
    def buildDir = dir.getAbsolutePath().split('/') 
    buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/') 

    sourceSets.test.compileClasspath += files(buildDir) 
    sourceSets.test.runtimeClasspath += files(buildDir) 
} 

dependencies {  
    testCompile group: 'com.google.android', name: 'android', version: '4.1.1.4' 
    testCompile group: 'org.robolectric', name: 'robolectric', version: '2.0-alpha-3' 
    ... 
} 

악의적 인 classpath hackery는 R을 제외하고 내 주 프로젝트의 모든 클래스에 액세스 할 수 있습니다.빌드 디렉토리에 272,파일 만은 compileTestJava 작업하는 동안이 오류가 발생합니다 :

/.../MainActivityTest.java:16: error: cannot find symbol 
       final String appName = activity.getResources().getString(R.string.app_name); 
                     ^
    symbol: variable string 
    location: class R 
1 error 
:test:compileTestJava FAILED 

바로, 새로운 빌드 시스템 Robolectric 테스트를 실행하는 더 나은 방법이 있어야합니다?

(Full source of the app)

+2

나는 이것이 작동하지 않을 것이라고 생각합니다.robolectric에는 내부 리소스가있어 실제 리소스를 찾을 수있는 곳 (예 : 종속성으로 프로젝트를 확장 할 수있는 영역)은 gradle 플러그인의 역할과 관련이 있습니다. 호환 가능하도록 Robolectric 개발자와 협력해야합니다. 할일 목록에 있습니다. –

+0

@av 입력에 감사드립니다. – passy

+0

새로운 Android Studio ide에서 grado를 사용하여 robolectric을 실행하는 방법이 있습니까? – Imanol

답변

27

나는이 같은 문제에 걸쳐 실행되고 이것이 내가 생각 해낸 것입니다. 테스트를 위해 별도의 프로젝트를 만드는 대신 Robolectric 테스트를위한 소스 세트를 만들고 "점검"에 의존 할 새로운 작업을 추가했습니다. 내 종속성을 포함 시켰습니다

apply plugin: 'android' 

sourceSets { 
    testLocal { 
     java.srcDir file('src/test/java') 
     resources.srcDir file('src/test/resources') 
    } 
} 

dependencies { 
    compile 'org.roboguice:roboguice:2.0' 
    compile 'com.google.android:support-v4:r6' 

    testLocalCompile 'junit:junit:4.8.2' 
    testLocalCompile 'org.robolectric:robolectric:2.1' 
    testLocalCompile 'com.google.android:android:4.0.1.2' 
    testLocalCompile 'com.google.android:support-v4:r6' 
    testLocalCompile 'org.roboguice:roboguice:2.0' 
} 

task localTest(type: Test, dependsOn: assemble) { 
    testClassesDir = sourceSets.testLocal.output.classesDir 

    android.sourceSets.main.java.srcDirs.each { dir -> 
     def buildDir = dir.getAbsolutePath().split('/') 
     buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/') 

     sourceSets.testLocal.compileClasspath += files(buildDir) 
     sourceSets.testLocal.runtimeClasspath += files(buildDir) 
    } 

    classpath = sourceSets.testLocal.runtimeClasspath 
} 

check.dependsOn localTest 

위해 나에게 이것을 얻을 수에 대한 지적 차단하고가는 : 당신의 질문에서 코드의 일부를 사용, 여기에 구축 (작업) 파일의 해당 비트는 , 내 사용자 정의 testLocal 소스 집합에 내 모든 compile 종속성을 반복해야했습니다.

gradle testLocal을 실행하면 src/test/java 내부의 테스트 만 실행되고 실행되며, gradle check을 실행하면 기본 android instrumentTest 소스 세트의 테스트 외에도이 테스트가 실행됩니다.

희망이 도움이됩니다.

+0

이것은 올바른 방향으로 큰 걸음, 감사합니다! Robolectric 테스트 러너가 실행 중입니다. 그러나 리소스에 액세스하려고하면 "android.content.res.Resources $ NotFoundException : unknown resource xxx"가 표시됩니다. 전체 스택 추적은 다음과 같습니다 : https://gist.github.com/passy/255bbd42ada11ad5fba7 – passy

+1

이것은 testrunner가'src/main'에있는'AndroidManifest.xml'을 찾을 수없는 것에서 오는 것 같습니다. RobolectricTestRunner 하위 클래스에서 이러한 경로를 설정할 수 있다고 생각하지만 이클립스를 사용하면 기본 프로젝트에 작업 디렉토리 만 설정하면됩니다. 그걸 gradle 파일에서 할 수 있을까요? – passy

+1

@passy 불행히도 그 문제가 발생하는 것을 보지 못했습니다. 그러나'AndroidManifest.xml'을 프로젝트 디렉토리의 루트에 넣고'build.gradle'에서 이와 비슷한 일을함으로써 설정된 매니페스트 소스를 오버라이드 할 수 있어야합니다 :'android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml'}}}'출처 : http://tools.android.com/tech-docs/new-build-system/user-guide – user2457888

8

업데이트 : Jake Wharton은 gradle-android-test-plugin을 방금 발표했습니다. https://github.com/square/gradle-android-test-plugin

매우 유선형 인 것처럼 보입니다. 특히 robolectric을 사용할 계획이라면 더욱 그렇습니다.


올드 답변

아래 robolectric-plugin 유망 보인다.

그들이 제공하는 샘플 build.gradle 파일은 다음과 같습니다

buildscript { 
    repositories { 
     mavenCentral() 
     maven { 
      url "https://oss.sonatype.org/content/repositories/snapshots" 
     } 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:0.4.2' 
     classpath 'com.novoda.gradle:robolectric-plugin:0.0.1-SNAPSHOT' 
    } 
} 

apply plugin: 'android' 
apply plugin: 'robolectric' 

repositories { 
    mavenCentral() 
    mavenLocal() 
    maven { 
     url "https://oss.sonatype.org/content/repositories/snapshots" 
    } 
} 

dependencies { 
    //compile files('libs/android-support-v4.jar') 

    // had to deploy to sonatype to get AAR to work 
    compile 'com.novoda:actionbarsherlock:4.3.2-SNAPSHOT' 

    robolectricCompile 'org.robolectric:robolectric:2.0' 
    robolectricCompile group: 'junit', name: 'junit', version: '4.+' 
} 

android { 
    compileSdkVersion 17 
    buildToolsVersion "17.0.0" 

    defaultConfig { 
     minSdkVersion 7 
     targetSdkVersion 17 
    } 
} 

안드로이드 Gradle을 플러그인 버전 0.5에서 작동하지 않는 것하지만 어쩌면 곧 것이다.

+0

buildype으로 분할 된 리소스를 지원하기 위해 Jake의 플러그인을 기다리고 있습니다. 현재는 그 문제를 해결할 수 없습니다.누군가 (몇 개월 전에)이 문제를 해결하기위한 패치를 작성했지만 아무런 코멘트가 없었으며 받아 들여지지 않았습니다. 그때까지는 허용 된 대답의 방법이 효과적입니다. –

+2

Jake Wharton의 플러그인이 이제 비추천입니까? – Flame

+0

예. 표준 안드로이드 테스트 인프라 스트럭처로 이동하는 데는 단호함이있는 것 같습니다. Robolectric은 어떤 경우에는 여전히 유용하지만, 순수 자바 클래스의 대부분이 junit 및 Android 특정 프레임 워크로 테스트 된 유닛 인 자바 라이브러리 모듈이기 때문에 애플리케이션 관리가 더 쉬웠다. –

관련 문제