【问题标题】:Robolectric with Gradle: Resources not found使用 Gradle 的 Robolectric:找不到资源
【发布时间】:2013-05-15 00:05:33
【问题描述】:

我正在尝试将我的 Robolectric 测试与新的 Gradle Android 构建系统一起运行,但我无法访问我的主项目的资源。

为了避免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'
    ...
}

邪恶的类路径黑客允许我访问我的主项目的所有类,除了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)

【问题讨论】:

  • 我认为这行不通。在 robolectric 中还有一些其他内部内容,关于在哪里可以找到无法使用 gradle 插件工作(或扩展到具有依赖项的项目)的实际资源。我需要与 Robolectric 开发人员合作以使其兼容。它在我的待办事项清单上。
  • 感谢@Xav 的输入。
  • 那么有没有办法在新的 Android Studio ide 中使用 gradle 运行 robolectric?
  • @Xav 有没有机会通过 Gradle 尽快让它工作?你能指出 Robolectric 的 github 页面上的一个问题吗?

标签: android gradle robolectric


【解决方案1】:

我遇到了同样的问题,这就是我想出的。我没有为测试创建单独的项目,而是为 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 源集中的测试。

希望这会有所帮助!

【讨论】:

  • 这看起来是朝着正确方向迈出的一大步,谢谢! Robolectric 测试运行程序正在执行,但是,当任何尝试访问资源时,我现在收到“android.content.res.Resources$NotFoundException:未知资源 xxx”。完整的堆栈跟踪:gist.github.com/passy/255bbd42ada11ad5fba7
  • 这似乎来自于测试运行者无法找到位于src/mainAndroidManifest.xml。我想我可以在 RobolectricTestRunner 子类中设置这些路径,但是使用 Eclipse 我只需将工作目录设置为主项目。我可以在 gradle 文件中这样做吗?
  • @passy 不幸的是我还没有看到这个问题出现。但是,您应该能够将您的AndroidManifest.xml 放在项目目录的根目录中,并通过在build.gradle 中执行类似的操作来覆盖清单源集:android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml' } } } 源:tools.android.com/tech-docs/new-build-system/user-guide
  • 再次感谢@user2457888。 :) 我将localTest 任务中的workingDir 设置为src/main,现在它找到了AndroidManifest.xml 和所有资源。
  • @alex - 我想通了!进入模块设置,在依赖项中,添加一个新库,从 maven 中选择,然后添加 robolectric。更改它的范围以进行编译。目前可以使用,但如果您同时使用 instrumentationTest 可能会产生干扰。
【解决方案2】:

更新: 杰克沃顿刚刚宣布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 Gradle 插件 0.5 版,但也许很快就会。

【讨论】:

  • 我正在焦急地等待 Jake 的插件来支持按 buildType 拆分的资源。目前它似乎无法处理这个问题。有人写了一个补丁来解决这个问题(几个月前),但是上面没有 cmets 并且没有被接受。在那之前,接受的答案中的方法是有效的。
  • 似乎 Jake Wharton 的插件现在已被弃用?
  • 是的。似乎急于转向标准的 android 测试基础设施。 Robolectric 在某些情况下仍然有用,但我发现管理应用程序更容易,因此我的大多数纯 java 类都是 java 库模块,它们使用 junit 进行单元测试,而特定于 Android 的模块使用 android 测试框架。
  • 新旧答案都参考了弃用的插件
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
  • 2022-11-24
相关资源
最近更新 更多