2013-05-20 42 views
30

我试图与新的Gradle Android构建系统一起运行我的Robolectric测试,但是我一直在访问我的主项目的资源。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 

build.gradletest/目前看起来是这样的:

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,它存在为.class文件中生成目录,但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

感谢您的输入,@Xav。 – passy

+0

那么还有没有在新的Android Studio IDE中使用gradle运行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 testrunner正在执行,但是,当任何尝试访问资源时,我现在都会收到“android.content.res.Resources $ NotFoundException:unknown resource xxx”。完整堆栈跟踪这里:https://gist.github.com/passy/255bbd42ada11ad5fba7 – passy

+1

这似乎来自TestRunner的是找不到'AndroidManifest.xml',它位于'SRC/main'。我想我可以在RobolectricTestRunner子类中设置这些路径,但对于Eclipse,我只需将工作目录设置为主项目。我可以在gradle文件中做到这一点吗? – passy

+1

@passy不幸的是我没有看到这个问题出现。但是,你应该能够把你的'AndroidManifest.xml'在项目的根目录下,并覆盖清单源在'build.gradle'做类似于这样设置:'Android版{ sourceSets { 主要{ manifest.srcFile '的AndroidManifest.xml'}}}'资料来源:http://tools.android.com/tech-docs/new-build-system/user-guide – user2457888

8

更新: 杰克沃顿刚刚宣布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 
    } 
} 

它似乎并不与Android摇篮插件版本0.5工作,但也许它会很快。

+0

我焦急地等待Jake的插件来支持由buildType分割的资源。目前似乎无法解决这个问题。有人写了一个补丁来解决这个问题(几个月前),但没有评论,也没有被接受。在此之前,接受答案中的方法正在起作用。 –

+2

似乎像杰克沃顿的插件现在已被弃用? – Flame

+0

是的。似乎有一个转向标准的android测试基础设施的乱舞。 Robolectric对于某些情况仍然有帮助,但是我发现管理应用程序更容易,因此我的大多数纯Java类都是java库模块,它们都是通过junit和Android测试框架对Android进行单元测试的。 –